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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [gas/] [config/] [obj-evax.c] - Blame information for rev 818

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 205 julius
/* obj-evax.c - EVAX (openVMS/Alpha) object file format.
2
   Copyright 1996, 1997, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
3
   Contributed by Klaus Kämpf (kkaempf@progis.de) of
4
     proGIS Software, Aachen, Germany.
5
   Extensively enhanced by Douglas Rupp of AdaCore.
6
 
7
   This file is part of GAS, the GNU Assembler
8
 
9
   GAS is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3, or (at your option)
12
   any later version.
13
 
14
   GAS is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with GAS; see the file COPYING.  If not, write to
21
   the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
22
   MA 02110-1301, USA.  */
23
 
24
#define OBJ_HEADER "obj-evax.h"
25
 
26
#include "bfd.h"
27
#include "vms.h"
28
#include "as.h"
29
#include "subsegs.h"
30
#include "struc-symbol.h"
31
#include "safe-ctype.h"
32
 
33
static void s_evax_weak (int);
34
static unsigned int crc32 (unsigned char *, int);
35
static char *encode_32 (unsigned int);
36
static char *encode_16 (unsigned int);
37
static int decode_16 (const char *);
38
 
39
const pseudo_typeS obj_pseudo_table[] =
40
{
41
  { "weak", s_evax_weak, 0},
42
  {0, 0, 0},
43
};                              /* obj_pseudo_table */
44
 
45
void obj_read_begin_hook () {}
46
 
47
/* Handle the weak specific pseudo-op.  */
48
 
49
static void
50
s_evax_weak (int ignore ATTRIBUTE_UNUSED)
51
{
52
  char *name;
53
  int c;
54
  symbolS *symbolP;
55
  char *stop = NULL;
56
  char stopc;
57
 
58
  if (flag_mri)
59
    stop = mri_comment_field (&stopc);
60
 
61
  do
62
    {
63
      name = input_line_pointer;
64
      c = get_symbol_end ();
65
      symbolP = symbol_find_or_make (name);
66
      *input_line_pointer = c;
67
      SKIP_WHITESPACE ();
68
      S_SET_WEAK (symbolP);
69
      if (c == ',')
70
        {
71
          input_line_pointer++;
72
          SKIP_WHITESPACE ();
73
          if (*input_line_pointer == '\n')
74
            c = '\n';
75
        }
76
    }
77
  while (c == ',');
78
 
79
  if (flag_mri)
80
    mri_comment_end (stop, stopc);
81
 
82
  demand_empty_rest_of_line ();
83
}
84
 
85
void
86
evax_symbol_new_hook (symbolS *sym)
87
{
88
  struct evax_private_udata_struct *udata;
89
 
90
  udata = (struct evax_private_udata_struct *)
91
    xmalloc (sizeof (struct evax_private_udata_struct));
92
 
93
  udata->bsym = symbol_get_bfdsym (sym);
94
  udata->enbsym = NULL;
95
  udata->origname = xstrdup (S_GET_NAME (sym));
96
  udata->lkindex = 0;
97
  symbol_get_bfdsym(sym)->udata.p = (PTR) udata;
98
}
99
 
100
void
101
evax_frob_symbol (symbolS *sym, int *punt)
102
{
103
  const char *symname = S_GET_NAME (sym);
104
  int symlen = strlen (symname);
105
  asymbol *symbol = symbol_get_bfdsym (sym);
106
 
107
  if (symlen > 4
108
      && strcmp (symname + symlen - 4, "..en") == 0
109
      && S_GET_SEGMENT (sym) == undefined_section)
110
    {
111
      symbol_clear_used_in_reloc (sym);
112
      *punt = 1;
113
    }
114
 
115
  else if ((symbol->flags & BSF_GLOBAL) && (symbol->flags & BSF_FUNCTION))
116
    {
117
      struct evax_private_udata_struct *udata
118
        = (struct evax_private_udata_struct *)symbol->udata.p;
119
 
120
      /* Fix up equates of function definitions.  */
121
      while (udata->enbsym == NULL)
122
        {
123
          /* ??? Equates have been resolved at this point so their
124
             expression is O_constant; but they previously were
125
             O_symbol and we hope the equated symbol is still there.  */
126
          sym = symbol_get_value_expression (sym)->X_add_symbol;
127
          if (sym == NULL)
128
            abort ();
129
          symbol = symbol_get_bfdsym (sym);
130
          udata->enbsym
131
            = ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym;
132
        }
133
    }
134
}
135
 
136
void
137
evax_frob_file_before_adjust (void)
138
{
139
  struct alpha_linkage_fixups *l;
140
  segT current_section = now_seg;
141
  int current_subsec = now_subseg;
142
  segment_info_type *seginfo;
143
  int linkage_index = 1;
144
 
145
  subseg_set (alpha_link_section, 0);
146
  seginfo = seg_info (alpha_link_section);
147
 
148
  for (l = alpha_linkage_fixup_root; l != NULL; l = l->next)
149
    {
150
      if (S_GET_SEGMENT (l->fixp->fx_addsy) == alpha_link_section)
151
        {
152
          symbolS * entry_sym;
153
          fixS *fixpentry, *fixppdesc, *fixtail;
154
 
155
          fixtail = seginfo->fix_tail;
156
 
157
          /* Replace the linkage with the local symbols */
158
          entry_sym = symbol_find
159
            (((struct evax_private_udata_struct *)symbol_get_bfdsym (l->fixp->fx_addsy)->udata.p)->enbsym->name);
160
          if (!entry_sym)
161
            abort ();
162
          fixpentry = fix_new (l->fixp->fx_frag, l->fixp->fx_where, 8,
163
                               entry_sym, l->fixp->fx_offset, 0,
164
                               BFD_RELOC_64);
165
          fixppdesc = fix_new (l->fixp->fx_frag, l->fixp->fx_where+8, 8,
166
                               l->fixp->fx_addsy, l->fixp->fx_offset, 0,
167
                               BFD_RELOC_64);
168
          l->fixp->fx_size = 0;
169
          l->fixp->fx_done = 1;
170
 
171
          /* If not already at the tail, splice the new fixups into
172
             the chain right after the one we are nulling out */
173
          if (fixtail != l->fixp)
174
            {
175
              fixppdesc->fx_next = l->fixp->fx_next;
176
              l->fixp->fx_next = fixpentry;
177
              fixtail->fx_next = 0;
178
              seginfo->fix_tail = fixtail;
179
            }
180
        }
181
      else
182
        {
183
          ((struct evax_private_udata_struct *)
184
           symbol_get_bfdsym (l->label)->udata.p)->lkindex = linkage_index;
185
 
186
          l->fixp->fx_addnumber = linkage_index;
187
 
188
          linkage_index += 2;
189
        }
190
    }
191
 
192
  subseg_set (current_section, current_subsec);
193
}
194
 
195
void
196
evax_frob_file_before_fix (void)
197
{
198
  /* Now that the fixups are done earlier, we need to transfer the values
199
     into the BFD symbols before calling fix_segment (ideally should not
200
     be done also later).  */
201
  if (symbol_rootP)
202
    {
203
      symbolS *symp;
204
 
205
      /* Set the value into the BFD symbol.  Up til now the value
206
         has only been kept in the gas symbolS struct.  */
207
      for (symp = symbol_rootP; symp; symp = symbol_next (symp))
208
        symbol_get_bfdsym (symp)->value = S_GET_VALUE (symp);
209
    }
210
}
211
 
212
/* The length is computed from the maximum allowable length of 64 less the
213
   4 character ..xx extension that must be preserved (removed before
214
   krunching and appended back on afterwards).  The $<nnn>.. prefix is
215
   also removed and prepened back on, but doesn't enter into the length
216
   computation because symbols with that prefix are always resolved
217
   by the assembler and will never appear in the symbol table. At least
218
   I hope that's true, TBD.  */
219
#define MAX_LABEL_LENGTH 60
220
 
221
static char *shorten_identifier (char *);
222
static int is_truncated_identifier (char *);
223
 
224
char *
225
evax_shorten_name (char *id)
226
{
227
  int prefix_dotdot = 0;
228
  char prefix [64];
229
  int len = strlen (id);
230
  int suffix_dotdot = len;
231
  char suffix [64];
232
  char *base_id;
233
 
234
  /* This test may be too conservative.  */
235
  if (len <= MAX_LABEL_LENGTH)
236
    return id;
237
 
238
  suffix [0] = 0;
239
  prefix [0] = 0;
240
 
241
  /* Check for ..xx suffix and save it.  */
242
  if (strncmp (&id[len-4], "..", 2) == 0)
243
    {
244
      suffix_dotdot = len - 4;
245
      strncpy (suffix, &id[len-4], 4);
246
      suffix [4] = 0;
247
    }
248
 
249
  /* Check for $<nnn>.. prefix and save it.  */
250
  if ((id[0] == '$') && ISDIGIT (id[1]))
251
    {
252
      int i;
253
 
254
      for (i=2; i < len; i++)
255
        {
256
          if (!ISDIGIT (id[i]))
257
            {
258
              if (id[i] == '.' && id [i+1] == '.')
259
                 {
260
                   prefix_dotdot = i+2;
261
                   strncpy (prefix, id, prefix_dotdot);
262
                   prefix [prefix_dotdot] = 0;
263
                 }
264
               break;
265
            }
266
        }
267
    }
268
 
269
  /* We only need worry about krunching the base symbol.  */
270
  base_id = xmalloc (suffix_dotdot - prefix_dotdot + 1);
271
  strncpy (base_id, &id[prefix_dotdot], suffix_dotdot - prefix_dotdot);
272
  base_id [suffix_dotdot - prefix_dotdot] = 0;
273
 
274
  if (strlen (base_id) > MAX_LABEL_LENGTH)
275
    {
276
      char new_id [4096];
277
      char *return_id;
278
 
279
      strcpy (new_id, base_id);
280
 
281
      /* Shorten it.  */
282
      strcpy (new_id, shorten_identifier (new_id));
283
 
284
      /* Prepend back the prefix if there was one.  */
285
      if (prefix_dotdot)
286
        {
287
          memmove (&new_id [prefix_dotdot], new_id, strlen (new_id) + 1);
288
          strncpy (new_id, prefix, prefix_dotdot);
289
        }
290
 
291
      /* Append back the suffix if there was one.  */
292
      if (strlen (suffix))
293
        strcat (new_id, suffix);
294
 
295
      /* Save it on the heap and return.  */
296
      return_id = xmalloc (strlen (new_id) + 1);
297
      strcpy (return_id, new_id);
298
 
299
      return return_id;
300
    }
301
  else
302
    return id;
303
}
304
 
305
/* The code below implements a mechanism for truncating long
306
   identifiers to an arbitrary length (set by MAX_LABEL_LENGTH).
307
 
308
   It attempts to make each truncated identifier unique by replacing
309
   part of the identifier with an encoded 32-bit CRC and an associated
310
   checksum (the checksum is used as a way to determine that the name
311
   was truncated).
312
 
313
   Note that both a portion of the start and of the end of the
314
   identifier may be kept.  The macro ID_SUFFIX_LENGTH will return the
315
   number of characters in the suffix of the identifier that should be
316
   kept.
317
 
318
   The portion of the identifier that is going to be removed is
319
   checksummed.  The checksum is then encoded as a 5-character string,
320
   the characters of which are then summed.  This sum is then encoded
321
   as a 3-character string.  Finally, the original length of the
322
   identifier is encoded as a 3-character string.
323
 
324
   These three strings are then concatenated together (along with an _h
325
   which further designates that the name was truncated):
326
 
327
   "original_identifier"_haaaaabbbccc
328
 
329
   aaaaa = 32-bit CRC
330
   bbb = length of original identifier
331
   ccc = sum of 32-bit CRC characters
332
 
333
   The resulting identifier will be MAX_LABEL_LENGTH characters long.
334
 
335
   */
336
 
337
 
338
/* Table used to convert an integer into a string.  */
339
 
340
static const char codings[] = {
341
  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
342
  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
343
  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
344
  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
345
  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_'};
346
 
347
/* The number of codings in the above table.  */
348
static const int number_of_codings = sizeof (codings) / sizeof (char);
349
 
350
/* Table used by decode_16 () to convert an encoded string back into
351
   an integer.  */
352
static char decodings[256];
353
 
354
/* Table used by the crc32 function to calcuate the checksum.  */
355
static unsigned int crc32_table[256] = {0, 0};
356
 
357
/* Given a string in BUF, calculate a 32-bit CRC for it.
358
 
359
   This is used as a reasonably unique hash for the given string.  */
360
 
361
static unsigned int
362
crc32 (unsigned char *buf, int len)
363
{
364
  unsigned int crc = 0xffffffff;
365
 
366
  if (! crc32_table[1])
367
    {
368
      /* Initialize the CRC table and the decoding table. */
369
      int i, j;
370
      unsigned int c;
371
 
372
      for (i = 0; i < 256; i++)
373
        {
374
          for (c = i << 24, j = 8; j > 0; --j)
375
            c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
376
          crc32_table[i] = c;
377
          decodings[i] = 0;
378
        }
379
      for (i = 0; i < number_of_codings; i++)
380
        decodings[codings[i] & 255] = i;
381
    }
382
 
383
  while (len--)
384
    {
385
      crc = (crc << 8) ^ crc32_table[(crc >> 24) ^ *buf];
386
      buf++;
387
    }
388
  return crc;
389
}
390
 
391
/* Encode the lower 32 bits of VALUE as a 5-character string.  */
392
 
393
static char *
394
encode_32 (unsigned int value)
395
{
396
  static char res[6];
397
  int x;
398
 
399
  res[5] = 0;
400
  for(x = 0; x < 5; x++)
401
    {
402
      res[x] = codings[value % number_of_codings];
403
      value = value / number_of_codings;
404
    }
405
  return res;
406
}
407
 
408
/* Encode the lower 16 bits of VALUE as a 3-character string.  */
409
 
410
static char *
411
encode_16 (unsigned int value)
412
{
413
  static char res[4];
414
  int x;
415
 
416
  res[3] = 0;
417
  for(x = 0; x < 3; x++)
418
    {
419
      res[x] = codings[value % number_of_codings];
420
      value = value / number_of_codings;
421
    }
422
  return res;
423
}
424
 
425
/* Convert the encoded string obtained from encode_16 () back into a
426
   16-bit integer.  */
427
 
428
static int
429
decode_16 (const char *string)
430
{
431
  return decodings[(int) string[2]] * number_of_codings * number_of_codings
432
    + decodings[(int) string[1]] * number_of_codings
433
    + decodings[(int) string[0]];
434
}
435
 
436
/* ID_SUFFIX_LENGTH is used to determine how many characters in the
437
   suffix of the identifier are to be preserved, if any.  */
438
 
439
#ifndef ID_SUFFIX_LENGTH
440
#define ID_SUFFIX_LENGTH(ID) (0)
441
#endif
442
 
443
/* Return a reasonably-unique version of NAME that is less than or
444
   equal to MAX_LABEL_LENGTH characters long.  The string returned from
445
   this function may be a copy of NAME; the function will never
446
   actually modify the contents of NAME.  */
447
 
448
static char newname[MAX_LABEL_LENGTH + 1];
449
 
450
static char *
451
shorten_identifier (char *name)
452
{
453
  int crc, len, sum, x, final_len;
454
  char *crc_chars;
455
  int suffix_length = ID_SUFFIX_LENGTH (name);
456
 
457
  if ((len = strlen (name)) <= MAX_LABEL_LENGTH)
458
    return name;
459
 
460
  final_len = MAX_LABEL_LENGTH - 2 - 5 - 3 - 3 - suffix_length;
461
  crc = crc32 ((unsigned char *)name + final_len,
462
               len - final_len - suffix_length);
463
  crc_chars = encode_32 (crc);
464
  sum = 0;
465
  for (x = 0; x < 5; x++)
466
    sum += crc_chars [x];
467
  strncpy (newname, name, final_len);
468
  newname [MAX_LABEL_LENGTH] = 0;
469
  /* Now append the suffix of the original identifier, if any.  */
470
  if (suffix_length)
471
  strncpy (newname + MAX_LABEL_LENGTH - suffix_length,
472
           name + len - suffix_length,
473
           suffix_length);
474
  strncpy (newname + final_len, "_h", 2);
475
  strncpy (newname + final_len + 2 , crc_chars, 5);
476
  strncpy (newname + final_len + 2 + 5, encode_16 (len), 3);
477
  strncpy (newname + final_len + 2 + 5 + 3, encode_16 (sum), 3);
478
  if (!is_truncated_identifier (newname))
479
    abort ();
480
  return newname;
481
}
482
 
483
/* Determine whether or not ID is a truncated identifier, and return a
484
   non-zero value if it is.  */
485
 
486
static int
487
is_truncated_identifier (char *id)
488
{
489
  char *ptr;
490
  int len = strlen (id);
491
  /* If it's not exactly MAX_LABEL_LENGTH characters long, it can't be
492
     a truncated identifier.  */
493
  if (len != MAX_LABEL_LENGTH)
494
    return 0;
495
 
496
  /* Start scanning backwards for a _h.  */
497
  len = len - 3 - 3 - 5 - 2;
498
  ptr = id + len;
499
  while (ptr >= id)
500
    {
501
      if (ptr[0] == '_' && ptr[1] == 'h')
502
        {
503
          /* Now see if the sum encoded in the identifer matches.  */
504
          int x, sum;
505
          sum = 0;
506
          for (x = 0; x < 5; x++)
507
            sum += ptr[x + 2];
508
          /* If it matches, this is probably a truncated identifier.  */
509
          if (sum == decode_16 (ptr + 5 + 2 + 3))
510
            return 1;
511
        }
512
      ptr--;
513
    }
514
  return 0;
515
}
516
 
517
/* end of obj-evax.c */

powered by: WebSVN 2.1.0

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