OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gold/] [testsuite/] [plugin_test.c] - Blame information for rev 196

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 khays
/* test_plugin.c -- simple linker plugin test
2
 
3
   Copyright 2008, 2009 Free Software Foundation, Inc.
4
   Written by Cary Coutant <ccoutant@google.com>.
5
 
6
   This file is part of gold.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
 
23
#ifdef HAVE_CONFIG_H
24
#include "config.h"
25
#endif
26
 
27
#include <stdio.h>
28
#include <stdlib.h>
29
#include <string.h>
30
#include "plugin-api.h"
31
 
32
struct claimed_file
33
{
34
  const char* name;
35
  void* handle;
36
  int nsyms;
37
  struct ld_plugin_symbol* syms;
38
  struct claimed_file* next;
39
};
40
 
41
struct sym_info
42
{
43
  int size;
44
  char* type;
45
  char* bind;
46
  char* vis;
47
  char* sect;
48
  char* name;
49
};
50
 
51
static struct claimed_file* first_claimed_file = NULL;
52
static struct claimed_file* last_claimed_file = NULL;
53
 
54
static ld_plugin_register_claim_file register_claim_file_hook = NULL;
55
static ld_plugin_register_all_symbols_read register_all_symbols_read_hook = NULL;
56
static ld_plugin_register_cleanup register_cleanup_hook = NULL;
57
static ld_plugin_add_symbols add_symbols = NULL;
58
static ld_plugin_get_symbols get_symbols = NULL;
59 163 khays
static ld_plugin_get_symbols get_symbols_v2 = NULL;
60 27 khays
static ld_plugin_add_input_file add_input_file = NULL;
61
static ld_plugin_message message = NULL;
62
static ld_plugin_get_input_file get_input_file = NULL;
63
static ld_plugin_release_input_file release_input_file = NULL;
64 159 khays
static ld_plugin_get_input_section_count get_input_section_count = NULL;
65
static ld_plugin_get_input_section_type get_input_section_type = NULL;
66
static ld_plugin_get_input_section_name get_input_section_name = NULL;
67
static ld_plugin_get_input_section_contents get_input_section_contents = NULL;
68
static ld_plugin_update_section_order update_section_order = NULL;
69
static ld_plugin_allow_section_ordering allow_section_ordering = NULL;
70 27 khays
 
71
#define MAXOPTS 10
72
 
73
static const char *opts[MAXOPTS];
74
static int nopts = 0;
75
 
76
enum ld_plugin_status onload(struct ld_plugin_tv *tv);
77
enum ld_plugin_status claim_file_hook(const struct ld_plugin_input_file *file,
78
                                      int *claimed);
79
enum ld_plugin_status all_symbols_read_hook(void);
80
enum ld_plugin_status cleanup_hook(void);
81
 
82
static void parse_readelf_line(char*, struct sym_info*);
83
 
84
enum ld_plugin_status
85
onload(struct ld_plugin_tv *tv)
86
{
87
  struct ld_plugin_tv *entry;
88
  int api_version = 0;
89
  int gold_version = 0;
90
  int i;
91
 
92
  for (entry = tv; entry->tv_tag != LDPT_NULL; ++entry)
93
    {
94
      switch (entry->tv_tag)
95
        {
96
        case LDPT_API_VERSION:
97
          api_version = entry->tv_u.tv_val;
98
          break;
99
        case LDPT_GOLD_VERSION:
100
          gold_version = entry->tv_u.tv_val;
101
          break;
102
        case LDPT_LINKER_OUTPUT:
103
          break;
104
        case LDPT_OPTION:
105
          if (nopts < MAXOPTS)
106
            opts[nopts++] = entry->tv_u.tv_string;
107
          break;
108
        case LDPT_REGISTER_CLAIM_FILE_HOOK:
109
          register_claim_file_hook = entry->tv_u.tv_register_claim_file;
110
          break;
111
        case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
112
          register_all_symbols_read_hook =
113
            entry->tv_u.tv_register_all_symbols_read;
114
          break;
115
        case LDPT_REGISTER_CLEANUP_HOOK:
116
          register_cleanup_hook = entry->tv_u.tv_register_cleanup;
117
          break;
118
        case LDPT_ADD_SYMBOLS:
119
          add_symbols = entry->tv_u.tv_add_symbols;
120
          break;
121
        case LDPT_GET_SYMBOLS:
122
          get_symbols = entry->tv_u.tv_get_symbols;
123
          break;
124 163 khays
        case LDPT_GET_SYMBOLS_V2:
125
          get_symbols_v2 = entry->tv_u.tv_get_symbols;
126
          break;
127 27 khays
        case LDPT_ADD_INPUT_FILE:
128
          add_input_file = entry->tv_u.tv_add_input_file;
129
          break;
130
        case LDPT_MESSAGE:
131
          message = entry->tv_u.tv_message;
132
          break;
133
        case LDPT_GET_INPUT_FILE:
134
          get_input_file = entry->tv_u.tv_get_input_file;
135
          break;
136
        case LDPT_RELEASE_INPUT_FILE:
137
          release_input_file = entry->tv_u.tv_release_input_file;
138
          break;
139 159 khays
        case LDPT_GET_INPUT_SECTION_COUNT:
140
          get_input_section_count = *entry->tv_u.tv_get_input_section_count;
141
          break;
142
        case LDPT_GET_INPUT_SECTION_TYPE:
143
          get_input_section_type = *entry->tv_u.tv_get_input_section_type;
144
          break;
145
        case LDPT_GET_INPUT_SECTION_NAME:
146
          get_input_section_name = *entry->tv_u.tv_get_input_section_name;
147
          break;
148
        case LDPT_GET_INPUT_SECTION_CONTENTS:
149
          get_input_section_contents = *entry->tv_u.tv_get_input_section_contents;
150
          break;
151
        case LDPT_UPDATE_SECTION_ORDER:
152
          update_section_order = *entry->tv_u.tv_update_section_order;
153
          break;
154
        case LDPT_ALLOW_SECTION_ORDERING:
155
          allow_section_ordering = *entry->tv_u.tv_allow_section_ordering;
156
          break;
157 27 khays
        default:
158
          break;
159
        }
160
    }
161
 
162
  if (message == NULL)
163
    {
164
      fprintf(stderr, "tv_message interface missing\n");
165
      return LDPS_ERR;
166
    }
167
 
168
  if (register_claim_file_hook == NULL)
169
    {
170
      fprintf(stderr, "tv_register_claim_file_hook interface missing\n");
171
      return LDPS_ERR;
172
    }
173
 
174
  if (register_all_symbols_read_hook == NULL)
175
    {
176
      fprintf(stderr, "tv_register_all_symbols_read_hook interface missing\n");
177
      return LDPS_ERR;
178
    }
179
 
180
  if (register_cleanup_hook == NULL)
181
    {
182
      fprintf(stderr, "tv_register_cleanup_hook interface missing\n");
183
      return LDPS_ERR;
184
    }
185
 
186
  (*message)(LDPL_INFO, "API version:   %d", api_version);
187
  (*message)(LDPL_INFO, "gold version:  %d", gold_version);
188
 
189
  for (i = 0; i < nopts; ++i)
190
    (*message)(LDPL_INFO, "option: %s", opts[i]);
191
 
192
  if ((*register_claim_file_hook)(claim_file_hook) != LDPS_OK)
193
    {
194
      (*message)(LDPL_ERROR, "error registering claim file hook");
195
      return LDPS_ERR;
196
    }
197
 
198
  if ((*register_all_symbols_read_hook)(all_symbols_read_hook) != LDPS_OK)
199
    {
200
      (*message)(LDPL_ERROR, "error registering all symbols read hook");
201
      return LDPS_ERR;
202
    }
203
 
204
  if ((*register_cleanup_hook)(cleanup_hook) != LDPS_OK)
205
    {
206
      (*message)(LDPL_ERROR, "error registering cleanup hook");
207
      return LDPS_ERR;
208
    }
209
 
210 159 khays
  if (get_input_section_count == NULL)
211
    {
212
      fprintf(stderr, "tv_get_input_section_count interface missing\n");
213
      return LDPS_ERR;
214
    }
215
 
216
  if (get_input_section_type == NULL)
217
    {
218
      fprintf(stderr, "tv_get_input_section_type interface missing\n");
219
      return LDPS_ERR;
220
    }
221
 
222
  if (get_input_section_name == NULL)
223
    {
224
      fprintf(stderr, "tv_get_input_section_name interface missing\n");
225
      return LDPS_ERR;
226
    }
227
 
228
  if (get_input_section_contents == NULL)
229
    {
230
      fprintf(stderr, "tv_get_input_section_contents interface missing\n");
231
      return LDPS_ERR;
232
    }
233
 
234
  if (update_section_order == NULL)
235
    {
236
      fprintf(stderr, "tv_update_section_order interface missing\n");
237
      return LDPS_ERR;
238
    }
239
 
240
  if (allow_section_ordering == NULL)
241
    {
242
      fprintf(stderr, "tv_allow_section_ordering interface missing\n");
243
      return LDPS_ERR;
244
    }
245
 
246 27 khays
  return LDPS_OK;
247
}
248
 
249
enum ld_plugin_status
250
claim_file_hook (const struct ld_plugin_input_file* file, int* claimed)
251
{
252
  int len;
253
  off_t end_offset;
254
  char buf[160];
255
  struct claimed_file* claimed_file;
256
  struct ld_plugin_symbol* syms;
257
  int nsyms = 0;
258
  int maxsyms = 0;
259
  FILE* irfile;
260
  struct sym_info info;
261
  int weak;
262
  int def;
263
  int vis;
264
  int is_comdat;
265
  int i;
266
 
267
  (*message)(LDPL_INFO,
268
             "%s: claim file hook called (offset = %ld, size = %ld)",
269
             file->name, (long)file->offset, (long)file->filesize);
270
 
271
  /* Look for the beginning of output from readelf -s.  */
272
  irfile = fdopen(file->fd, "r");
273
  (void)fseek(irfile, file->offset, SEEK_SET);
274
  end_offset = file->offset + file->filesize;
275
  len = fread(buf, 1, 13, irfile);
276
  if (len < 13 || strncmp(buf, "\nSymbol table", 13) != 0)
277
    return LDPS_OK;
278
 
279
  /* Skip the two header lines.  */
280
  (void) fgets(buf, sizeof(buf), irfile);
281
  (void) fgets(buf, sizeof(buf), irfile);
282
 
283
  if (add_symbols == NULL)
284
    {
285
      fprintf(stderr, "tv_add_symbols interface missing\n");
286
      return LDPS_ERR;
287
    }
288
 
289
  /* Parse the output from readelf. The columns are:
290
     Index Value Size Type Binding Visibility Section Name.  */
291
  syms = (struct ld_plugin_symbol*)malloc(sizeof(struct ld_plugin_symbol) * 8);
292
  if (syms == NULL)
293
    return LDPS_ERR;
294
  maxsyms = 8;
295
  while (ftell(irfile) < end_offset
296
         && fgets(buf, sizeof(buf), irfile) != NULL)
297
    {
298
      parse_readelf_line(buf, &info);
299
 
300
      /* Ignore local symbols.  */
301
      if (strncmp(info.bind, "LOCAL", 5) == 0)
302
        continue;
303
 
304
      weak = strncmp(info.bind, "WEAK", 4) == 0;
305
      if (strncmp(info.sect, "UND", 3) == 0)
306
        def = weak ? LDPK_WEAKUNDEF : LDPK_UNDEF;
307
      else if (strncmp(info.sect, "COM", 3) == 0)
308
        def = LDPK_COMMON;
309
      else
310
        def = weak ? LDPK_WEAKDEF : LDPK_DEF;
311
 
312
      if (strncmp(info.vis, "INTERNAL", 8) == 0)
313
        vis = LDPV_INTERNAL;
314
      else if (strncmp(info.vis, "HIDDEN", 6) == 0)
315
        vis = LDPV_HIDDEN;
316
      else if (strncmp(info.vis, "PROTECTED", 9) == 0)
317
        vis = LDPV_PROTECTED;
318
      else
319
        vis = LDPV_DEFAULT;
320
 
321
      /* If the symbol is listed in the options list, special-case
322
         it as a comdat symbol.  */
323
      is_comdat = 0;
324
      for (i = 0; i < nopts; ++i)
325
        {
326
          if (info.name != NULL && strcmp(info.name, opts[i]) == 0)
327
            {
328
              is_comdat = 1;
329
              break;
330
            }
331
        }
332
 
333
      if (nsyms >= maxsyms)
334
        {
335
          syms = (struct ld_plugin_symbol*)
336
            realloc(syms, sizeof(struct ld_plugin_symbol) * maxsyms * 2);
337
          if (syms == NULL)
338
            return LDPS_ERR;
339
          maxsyms *= 2;
340
        }
341
 
342
      if (info.name == NULL)
343
        syms[nsyms].name = NULL;
344
      else
345
        {
346
          len = strlen(info.name);
347
          syms[nsyms].name = malloc(len + 1);
348
          strncpy(syms[nsyms].name, info.name, len + 1);
349
        }
350
      syms[nsyms].version = NULL;
351
      syms[nsyms].def = def;
352
      syms[nsyms].visibility = vis;
353
      syms[nsyms].size = info.size;
354
      syms[nsyms].comdat_key = is_comdat ? syms[nsyms].name : NULL;
355
      syms[nsyms].resolution = LDPR_UNKNOWN;
356
      ++nsyms;
357
    }
358
 
359
  claimed_file = (struct claimed_file*) malloc(sizeof(struct claimed_file));
360
  if (claimed_file == NULL)
361
    return LDPS_ERR;
362
 
363
  claimed_file->name = file->name;
364
  claimed_file->handle = file->handle;
365
  claimed_file->nsyms = nsyms;
366
  claimed_file->syms = syms;
367
  claimed_file->next = NULL;
368
  if (last_claimed_file == NULL)
369
    first_claimed_file = claimed_file;
370
  else
371
    last_claimed_file->next = claimed_file;
372
  last_claimed_file = claimed_file;
373
 
374
  (*message)(LDPL_INFO, "%s: claiming file, adding %d symbols",
375
             file->name, nsyms);
376
 
377
  if (nsyms > 0)
378
    (*add_symbols)(file->handle, nsyms, syms);
379
 
380
  *claimed = 1;
381
  return LDPS_OK;
382
}
383
 
384
enum ld_plugin_status
385
all_symbols_read_hook(void)
386
{
387
  int i;
388
  const char* res;
389
  struct claimed_file* claimed_file;
390
  struct ld_plugin_input_file file;
391
  FILE* irfile;
392
  off_t end_offset;
393
  struct sym_info info;
394
  int len;
395
  char buf[160];
396
  char* p;
397
  const char* filename;
398
 
399
  (*message)(LDPL_INFO, "all symbols read hook called");
400
 
401 163 khays
  if (get_symbols_v2 == NULL)
402 27 khays
    {
403 163 khays
      fprintf(stderr, "tv_get_symbols (v2) interface missing\n");
404 27 khays
      return LDPS_ERR;
405
    }
406
 
407
  for (claimed_file = first_claimed_file;
408
       claimed_file != NULL;
409
       claimed_file = claimed_file->next)
410
    {
411 163 khays
      (*get_symbols_v2)(claimed_file->handle, claimed_file->nsyms,
412 27 khays
                     claimed_file->syms);
413
 
414
      for (i = 0; i < claimed_file->nsyms; ++i)
415
        {
416
          switch (claimed_file->syms[i].resolution)
417
            {
418
            case LDPR_UNKNOWN:
419
              res = "UNKNOWN";
420
              break;
421
            case LDPR_UNDEF:
422
              res = "UNDEF";
423
              break;
424
            case LDPR_PREVAILING_DEF:
425
              res = "PREVAILING_DEF_REG";
426
              break;
427
            case LDPR_PREVAILING_DEF_IRONLY:
428
              res = "PREVAILING_DEF_IRONLY";
429
              break;
430 163 khays
            case LDPR_PREVAILING_DEF_IRONLY_EXP:
431
              res = "PREVAILING_DEF_IRONLY_EXP";
432
              break;
433 27 khays
            case LDPR_PREEMPTED_REG:
434
              res = "PREEMPTED_REG";
435
              break;
436
            case LDPR_PREEMPTED_IR:
437
              res = "PREEMPTED_IR";
438
              break;
439
            case LDPR_RESOLVED_IR:
440
              res = "RESOLVED_IR";
441
              break;
442
            case LDPR_RESOLVED_EXEC:
443
              res = "RESOLVED_EXEC";
444
              break;
445
            case LDPR_RESOLVED_DYN:
446
              res = "RESOLVED_DYN";
447
              break;
448
            default:
449
              res = "?";
450
              break;
451
            }
452
          (*message)(LDPL_INFO, "%s: %s: %s", claimed_file->name,
453
                     claimed_file->syms[i].name, res);
454
        }
455
    }
456
 
457
  if (add_input_file == NULL)
458
    {
459
      fprintf(stderr, "tv_add_input_file interface missing\n");
460
      return LDPS_ERR;
461
    }
462
  if (get_input_file == NULL)
463
    {
464
      fprintf(stderr, "tv_get_input_file interface missing\n");
465
      return LDPS_ERR;
466
    }
467
  if (release_input_file == NULL)
468
    {
469
      fprintf(stderr, "tv_release_input_file interface missing\n");
470
      return LDPS_ERR;
471
    }
472
 
473
  for (claimed_file = first_claimed_file;
474
       claimed_file != NULL;
475
       claimed_file = claimed_file->next)
476
    {
477
      (*get_input_file) (claimed_file->handle, &file);
478
 
479
      /* Look for the beginning of output from readelf -s.  */
480
      irfile = fdopen(file.fd, "r");
481
      (void)fseek(irfile, file.offset, SEEK_SET);
482
      end_offset = file.offset + file.filesize;
483
      len = fread(buf, 1, 13, irfile);
484
      if (len < 13 || strncmp(buf, "\nSymbol table", 13) != 0)
485
        {
486
          fprintf(stderr, "%s: can't re-read original input file\n",
487
                  claimed_file->name);
488
          return LDPS_ERR;
489
        }
490
 
491
      /* Skip the two header lines.  */
492
      (void) fgets(buf, sizeof(buf), irfile);
493
      (void) fgets(buf, sizeof(buf), irfile);
494
 
495
      filename = NULL;
496
      while (ftell(irfile) < end_offset
497
             && fgets(buf, sizeof(buf), irfile) != NULL)
498
        {
499
          parse_readelf_line(buf, &info);
500
 
501
          /* Look for file name.  */
502
          if (strncmp(info.type, "FILE", 4) == 0)
503
            {
504
              len = strlen(info.name);
505
              p = malloc(len + 1);
506
              strncpy(p, info.name, len + 1);
507
              filename = p;
508
              break;
509
            }
510
        }
511
 
512
      (*release_input_file) (claimed_file->handle);
513
 
514
      if (filename == NULL)
515
        filename = claimed_file->name;
516
 
517
      if (claimed_file->nsyms == 0)
518
        continue;
519
 
520
      if (strlen(filename) >= sizeof(buf))
521
        {
522
          (*message)(LDPL_FATAL, "%s: filename too long", filename);
523
          return LDPS_ERR;
524
        }
525
      strcpy(buf, filename);
526
      p = strrchr(buf, '.');
527
      if (p == NULL
528
          || (strcmp(p, ".syms") != 0
529
              && strcmp(p, ".c") != 0
530
              && strcmp(p, ".cc") != 0))
531
        {
532
          (*message)(LDPL_FATAL, "%s: filename has unknown suffix",
533
                     filename);
534
          return LDPS_ERR;
535
        }
536
      p[1] = 'o';
537
      p[2] = '\0';
538
      (*message)(LDPL_INFO, "%s: adding new input file", buf);
539
      (*add_input_file)(buf);
540
    }
541
 
542
  return LDPS_OK;
543
}
544
 
545
enum ld_plugin_status
546
cleanup_hook(void)
547
{
548
  (*message)(LDPL_INFO, "cleanup hook called");
549
  return LDPS_OK;
550
}
551
 
552
static void
553
parse_readelf_line(char* p, struct sym_info* info)
554
{
555
  int len;
556
 
557
  p += strspn(p, " ");
558
 
559
  /* Index field.  */
560
  p += strcspn(p, " ");
561
  p += strspn(p, " ");
562
 
563
  /* Value field.  */
564
  p += strcspn(p, " ");
565
  p += strspn(p, " ");
566
 
567
  /* Size field.  */
568
  info->size = atoi(p);
569
  p += strcspn(p, " ");
570
  p += strspn(p, " ");
571
 
572
  /* Type field.  */
573
  info->type = p;
574
  p += strcspn(p, " ");
575
  p += strspn(p, " ");
576
 
577
  /* Binding field.  */
578
  info->bind = p;
579
  p += strcspn(p, " ");
580
  p += strspn(p, " ");
581
 
582
  /* Visibility field.  */
583
  info->vis = p;
584
  p += strcspn(p, " ");
585
  p += strspn(p, " ");
586
 
587
  /* Section field.  */
588
  info->sect = p;
589
  p += strcspn(p, " ");
590
  p += strspn(p, " ");
591
 
592
  /* Name field.  */
593
  /* FIXME:  Look for version.  */
594
  len = strlen(p);
595
  if (len == 0)
596
    p = NULL;
597
  else if (p[len-1] == '\n')
598
    p[--len] = '\0';
599
  info->name = p;
600
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.