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 179

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