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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gas/] [config/] [obj-evax.c] - Blame information for rev 84

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

Line No. Rev Author Line
1 16 khays
/* 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
  /* Handle .linkage fixups.  */
149
  for (l = alpha_linkage_fixup_root; l != NULL; l = l->next)
150
    {
151
      if (S_GET_SEGMENT (l->fixp->fx_addsy) == alpha_link_section)
152
        {
153
          symbolS * entry_sym;
154
          fixS *fixpentry, *fixppdesc, *fixtail;
155
 
156
          fixtail = seginfo->fix_tail;
157
 
158
          /* Replace the linkage with the local symbols */
159
          entry_sym = symbol_find
160
            (((struct evax_private_udata_struct *)symbol_get_bfdsym (l->fixp->fx_addsy)->udata.p)->enbsym->name);
161
          if (!entry_sym)
162
            abort ();
163
          fixpentry = fix_new (l->fixp->fx_frag, l->fixp->fx_where, 8,
164
                               entry_sym, l->fixp->fx_offset, 0,
165
                               BFD_RELOC_64);
166
          fixppdesc = fix_new (l->fixp->fx_frag, l->fixp->fx_where+8, 8,
167
                               l->fixp->fx_addsy, l->fixp->fx_offset, 0,
168
                               BFD_RELOC_64);
169
          l->fixp->fx_size = 0;
170
          l->fixp->fx_done = 1;
171
 
172
          /* If not already at the tail, splice the new fixups into
173
             the chain right after the one we are nulling out */
174
          if (fixtail != l->fixp)
175
            {
176
              fixppdesc->fx_next = l->fixp->fx_next;
177
              l->fixp->fx_next = fixpentry;
178
              fixtail->fx_next = 0;
179
              seginfo->fix_tail = fixtail;
180
            }
181
        }
182
      else
183
        {
184
          ((struct evax_private_udata_struct *)
185
           symbol_get_bfdsym (l->label)->udata.p)->lkindex = linkage_index;
186
 
187
          l->fixp->fx_addnumber = linkage_index;
188
 
189
          linkage_index += 2;
190
        }
191
    }
192
 
193
  subseg_set (current_section, current_subsec);
194
}
195
 
196
void
197
evax_frob_file_before_fix (void)
198
{
199
  /* Now that the fixups are done earlier, we need to transfer the values
200
     into the BFD symbols before calling fix_segment (ideally should not
201
     be done also later).  */
202
  if (symbol_rootP)
203
    {
204
      symbolS *symp;
205
 
206
      /* Set the value into the BFD symbol.  Up til now the value
207
         has only been kept in the gas symbolS struct.  */
208
      for (symp = symbol_rootP; symp; symp = symbol_next (symp))
209
        symbol_get_bfdsym (symp)->value = S_GET_VALUE (symp);
210
    }
211
}
212
 
213
/* The length is computed from the maximum allowable length of 64 less the
214
   4 character ..xx extension that must be preserved (removed before
215
   krunching and appended back on afterwards).  The $<nnn>.. prefix is
216
   also removed and prepened back on, but doesn't enter into the length
217
   computation because symbols with that prefix are always resolved
218
   by the assembler and will never appear in the symbol table. At least
219
   I hope that's true, TBD.  */
220
#define MAX_LABEL_LENGTH 60
221
 
222
static char *shorten_identifier (char *);
223
static int is_truncated_identifier (char *);
224
 
225
char *
226
evax_shorten_name (char *id)
227
{
228
  int prefix_dotdot = 0;
229
  char prefix [64];
230
  int len = strlen (id);
231
  int suffix_dotdot = len;
232
  char suffix [64];
233
  char *base_id;
234
 
235
  /* This test may be too conservative.  */
236
  if (len <= MAX_LABEL_LENGTH)
237
    return id;
238
 
239
  suffix [0] = 0;
240
  prefix [0] = 0;
241
 
242
  /* Check for ..xx suffix and save it.  */
243
  if (strncmp (&id[len-4], "..", 2) == 0)
244
    {
245
      suffix_dotdot = len - 4;
246
      strncpy (suffix, &id[len-4], 4);
247
      suffix [4] = 0;
248
    }
249
 
250
  /* Check for $<nnn>.. prefix and save it.  */
251
  if ((id[0] == '$') && ISDIGIT (id[1]))
252
    {
253
      int i;
254
 
255
      for (i=2; i < len; i++)
256
        {
257
          if (!ISDIGIT (id[i]))
258
            {
259
              if (id[i] == '.' && id [i+1] == '.')
260
                 {
261
                   prefix_dotdot = i+2;
262
                   strncpy (prefix, id, prefix_dotdot);
263
                   prefix [prefix_dotdot] = 0;
264
                 }
265
               break;
266
            }
267
        }
268
    }
269
 
270
  /* We only need worry about krunching the base symbol.  */
271
  base_id = xmalloc (suffix_dotdot - prefix_dotdot + 1);
272
  strncpy (base_id, &id[prefix_dotdot], suffix_dotdot - prefix_dotdot);
273
  base_id [suffix_dotdot - prefix_dotdot] = 0;
274
 
275
  if (strlen (base_id) > MAX_LABEL_LENGTH)
276
    {
277
      char new_id [4096];
278
      char *return_id;
279
 
280
      strcpy (new_id, base_id);
281
 
282
      /* Shorten it.  */
283
      strcpy (new_id, shorten_identifier (new_id));
284
 
285
      /* Prepend back the prefix if there was one.  */
286
      if (prefix_dotdot)
287
        {
288
          memmove (&new_id [prefix_dotdot], new_id, strlen (new_id) + 1);
289
          strncpy (new_id, prefix, prefix_dotdot);
290
        }
291
 
292
      /* Append back the suffix if there was one.  */
293
      if (strlen (suffix))
294
        strcat (new_id, suffix);
295
 
296
      /* Save it on the heap and return.  */
297
      return_id = xmalloc (strlen (new_id) + 1);
298
      strcpy (return_id, new_id);
299
 
300
      return return_id;
301
    }
302
  else
303
    return id;
304
}
305
 
306
/* The code below implements a mechanism for truncating long
307
   identifiers to an arbitrary length (set by MAX_LABEL_LENGTH).
308
 
309
   It attempts to make each truncated identifier unique by replacing
310
   part of the identifier with an encoded 32-bit CRC and an associated
311
   checksum (the checksum is used as a way to determine that the name
312
   was truncated).
313
 
314
   Note that both a portion of the start and of the end of the
315
   identifier may be kept.  The macro ID_SUFFIX_LENGTH will return the
316
   number of characters in the suffix of the identifier that should be
317
   kept.
318
 
319
   The portion of the identifier that is going to be removed is
320
   checksummed.  The checksum is then encoded as a 5-character string,
321
   the characters of which are then summed.  This sum is then encoded
322
   as a 3-character string.  Finally, the original length of the
323
   identifier is encoded as a 3-character string.
324
 
325
   These three strings are then concatenated together (along with an _h
326
   which further designates that the name was truncated):
327
 
328
   "original_identifier"_haaaaabbbccc
329
 
330
   aaaaa = 32-bit CRC
331
   bbb = length of original identifier
332
   ccc = sum of 32-bit CRC characters
333
 
334
   The resulting identifier will be MAX_LABEL_LENGTH characters long.
335
 
336
   */
337
 
338
 
339
/* Table used to convert an integer into a string.  */
340
 
341
static const char codings[] = {
342
  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
343
  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
344
  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
345
  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
346
  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_'};
347
 
348
/* The number of codings in the above table.  */
349
static const int number_of_codings = sizeof (codings) / sizeof (char);
350
 
351
/* Table used by decode_16 () to convert an encoded string back into
352
   an integer.  */
353
static char decodings[256];
354
 
355
/* Table used by the crc32 function to calcuate the checksum.  */
356
static unsigned int crc32_table[256] = {0, 0};
357
 
358
/* Given a string in BUF, calculate a 32-bit CRC for it.
359
 
360
   This is used as a reasonably unique hash for the given string.  */
361
 
362
static unsigned int
363
crc32 (unsigned char *buf, int len)
364
{
365
  unsigned int crc = 0xffffffff;
366
 
367
  if (! crc32_table[1])
368
    {
369
      /* Initialize the CRC table and the decoding table. */
370
      int i, j;
371
      unsigned int c;
372
 
373
      for (i = 0; i < 256; i++)
374
        {
375
          for (c = i << 24, j = 8; j > 0; --j)
376
            c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
377
          crc32_table[i] = c;
378
          decodings[i] = 0;
379
        }
380
      for (i = 0; i < number_of_codings; i++)
381
        decodings[codings[i] & 255] = i;
382
    }
383
 
384
  while (len--)
385
    {
386
      crc = (crc << 8) ^ crc32_table[(crc >> 24) ^ *buf];
387
      buf++;
388
    }
389
  return crc;
390
}
391
 
392
/* Encode the lower 32 bits of VALUE as a 5-character string.  */
393
 
394
static char *
395
encode_32 (unsigned int value)
396
{
397
  static char res[6];
398
  int x;
399
 
400
  res[5] = 0;
401
  for(x = 0; x < 5; x++)
402
    {
403
      res[x] = codings[value % number_of_codings];
404
      value = value / number_of_codings;
405
    }
406
  return res;
407
}
408
 
409
/* Encode the lower 16 bits of VALUE as a 3-character string.  */
410
 
411
static char *
412
encode_16 (unsigned int value)
413
{
414
  static char res[4];
415
  int x;
416
 
417
  res[3] = 0;
418
  for(x = 0; x < 3; x++)
419
    {
420
      res[x] = codings[value % number_of_codings];
421
      value = value / number_of_codings;
422
    }
423
  return res;
424
}
425
 
426
/* Convert the encoded string obtained from encode_16 () back into a
427
   16-bit integer.  */
428
 
429
static int
430
decode_16 (const char *string)
431
{
432
  return decodings[(int) string[2]] * number_of_codings * number_of_codings
433
    + decodings[(int) string[1]] * number_of_codings
434
    + decodings[(int) string[0]];
435
}
436
 
437
/* ID_SUFFIX_LENGTH is used to determine how many characters in the
438
   suffix of the identifier are to be preserved, if any.  */
439
 
440
#ifndef ID_SUFFIX_LENGTH
441
#define ID_SUFFIX_LENGTH(ID) (0)
442
#endif
443
 
444
/* Return a reasonably-unique version of NAME that is less than or
445
   equal to MAX_LABEL_LENGTH characters long.  The string returned from
446
   this function may be a copy of NAME; the function will never
447
   actually modify the contents of NAME.  */
448
 
449
static char newname[MAX_LABEL_LENGTH + 1];
450
 
451
static char *
452
shorten_identifier (char *name)
453
{
454
  int crc, len, sum, x, final_len;
455
  char *crc_chars;
456
  int suffix_length = ID_SUFFIX_LENGTH (name);
457
 
458
  if ((len = strlen (name)) <= MAX_LABEL_LENGTH)
459
    return name;
460
 
461
  final_len = MAX_LABEL_LENGTH - 2 - 5 - 3 - 3 - suffix_length;
462
  crc = crc32 ((unsigned char *)name + final_len,
463
               len - final_len - suffix_length);
464
  crc_chars = encode_32 (crc);
465
  sum = 0;
466
  for (x = 0; x < 5; x++)
467
    sum += crc_chars [x];
468
  strncpy (newname, name, final_len);
469
  newname [MAX_LABEL_LENGTH] = 0;
470
  /* Now append the suffix of the original identifier, if any.  */
471
  if (suffix_length)
472
  strncpy (newname + MAX_LABEL_LENGTH - suffix_length,
473
           name + len - suffix_length,
474
           suffix_length);
475
  strncpy (newname + final_len, "_h", 2);
476
  strncpy (newname + final_len + 2 , crc_chars, 5);
477
  strncpy (newname + final_len + 2 + 5, encode_16 (len), 3);
478
  strncpy (newname + final_len + 2 + 5 + 3, encode_16 (sum), 3);
479
  if (!is_truncated_identifier (newname))
480
    abort ();
481
  return newname;
482
}
483
 
484
/* Determine whether or not ID is a truncated identifier, and return a
485
   non-zero value if it is.  */
486
 
487
static int
488
is_truncated_identifier (char *id)
489
{
490
  char *ptr;
491
  int len = strlen (id);
492
  /* If it's not exactly MAX_LABEL_LENGTH characters long, it can't be
493
     a truncated identifier.  */
494
  if (len != MAX_LABEL_LENGTH)
495
    return 0;
496
 
497
  /* Start scanning backwards for a _h.  */
498
  len = len - 3 - 3 - 5 - 2;
499
  ptr = id + len;
500
  while (ptr >= id)
501
    {
502
      if (ptr[0] == '_' && ptr[1] == 'h')
503
        {
504
          /* Now see if the sum encoded in the identifer matches.  */
505
          int x, sum;
506
          sum = 0;
507
          for (x = 0; x < 5; x++)
508
            sum += ptr[x + 2];
509
          /* If it matches, this is probably a truncated identifier.  */
510
          if (sum == decode_16 (ptr + 5 + 2 + 3))
511
            return 1;
512
        }
513
      ptr--;
514
    }
515
  return 0;
516
}
517
 
518
/* 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.