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 160

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

powered by: WebSVN 2.1.0

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