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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [gold/] [testsuite/] [plugin_test.c] - Blame information for rev 860

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

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

powered by: WebSVN 2.1.0

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