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 27

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

powered by: WebSVN 2.1.0

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