diff options
author | Tristan Gingold <gingold@adacore.com> | 2009-03-03 10:04:58 +0000 |
---|---|---|
committer | Tristan Gingold <gingold@adacore.com> | 2009-03-03 10:04:58 +0000 |
commit | 198f1251457bf99a3f3aec2d2db1977b99e6f519 (patch) | |
tree | bb675f11b07ece8dcefe50aed8284f06ab32ab16 /gas/config/obj-evax.c | |
parent | 54b70fa3143fa8c444e8d4bec971f868becf7e49 (diff) | |
download | gdb-198f1251457bf99a3f3aec2d2db1977b99e6f519.zip gdb-198f1251457bf99a3f3aec2d2db1977b99e6f519.tar.gz gdb-198f1251457bf99a3f3aec2d2db1977b99e6f519.tar.bz2 |
2009-03-03 Tristan Gingold <gingold@adacore.com>
Eric Botcazou <ebotcazou@adacore.com>
Douglas B Rupp <rupp@gnat.com>
* doc/as.texinfo (Overview): Mention -replace/-noreplace options
for Alpha.
* doc/c-alpha.texi (Alpha Options): Document -replace/-noreplace.
* config/tc-alpha.h (TC_VALIDATE_FIX_SUB): Define to 1 (evax).
(OBJ_SYMFIELD_TYPE): Remove.
(tc_canonicalize_symbol_name): Define to evax_shorten_name.
(TC_IMPLICIT_LCOMM_ALIGNMENT): For alignment to 3 on evax.
(tc_frob_file_before_fix): Do not defined on evax.
* config/tc-alpha.c: Always includes dwarf2dbg.h.
Include vms.h if OBJ_EVAX.
(struct alpha_fixup): Add xtrasym and procsym (evax only).
(enum alpha_macro_arg): Remove trailing comma.
(md_longopts): Add replace and noreplace arguments (evax only).
(alpha_evax_proc_hash): New variable.
(alpha_link_section): Make it global.
(alpha_ctors_section, alpha_dtors_section): Removed.
(alpha_ctors_symbol, alpha_dtors_symbol): Ditto.
(alpha_lit8_section): Ifndef'ed on evax.
(alpha_lit8_symbol): Ditto.
(alpha_prologue_label): New variable.
(alpha_linkage_symbol): New variable (evax only).
(alpha_flag_replace): Ditto.
(struct alpha_evax_procs): Add handler and handler_data field.
(alpha_evax_proc): Now of type pointer.
(alpha_linkage_fixup_root, alpha_linkage_fixup_tail): New variables.
(struct alpha_reloc_tag): Add sym and psym fields (evax only).
(get_alpha_reloc_tag): Initialize sym and psym fields (evax only).
(alpha_adjust_relocs): Ifndef'ed on evax.
(load_expression): Add opname argument.
Implement LDA/BSR optimization for evax.
(emit_lda): Adjust for new prototype of load_expression.
(emit_ir_load): Ditto. Do not nothing for GP if ..lk symbols.
(emit_loadstore): Likewise.
(emit_ldXu): Likewise.
(emit_stX): Likewise.
(emit_jsrjmp): Likewise. Implement LDA/BSR optimization for evax.
(emit_ldgp): Avoid warning in evax case.
(add_to_link_pool): Make it static. Return symbolic expression rather
than number expression for the offset.
(s_alpha_text): Create .text symbol for evax if not already created.
(s_alpha_comm): Do not create specific section for common symbol.
Fill common area with zeros for evax.
(s_alpha_prologue): Create alpha_prologue_label.
(s_alpha_section_name): New function (evax).
(s_alpha_section_word): Likewise.
(section_name): New static variabke moved out from ...
(s_alpha_section): ... here. Create new sections on demand.
(s_alpha_literals): New function (evax).
(s_alpha_ent): Create alpha_evax_proc instance and insert it in the
alpha_evax_proc_hash table.
(s_alpha_handler): New function (evax).
(s_alpha_frame): Adjust for new type of alpha_evax_proc.
(s_alpha_prologue): New function (evax).
(s_alpha_pdesc): Adjust for new type of alpha_evax_proc and new
handling of procedures with hash table.
Add support for condition handlers.
(s_alpha_linkage): Create linkage_fixup instance and chain it.
(s_alpha_fp_save): Adjust for new type of alpha_evax_proc.
(s_alpha_mask): Likewise.
(s_alpha_fmask): Likewise.
(s_alpha_end): Clear alpha_evax_proc.
(s_alpha_align): Increase max_alignment to 16.
(alpha_print_token): Call print_expr_1 instead of print_expr.
(md_pseudo_table): Add "section", "literals", "handler" and
"handler_data" (evax). Do not ignore "prologue" on evax.
Fix indentation.
(md_begin): Create hash table for alpha_evax_proc_hash.
(md_parse_option): Handle OPTION_REPLACE and OPTION_NOREPLACE.
(md_show_usage): Mention -replace/-noreplace for evax.
(md_apply_fix): Handle evax relocs (_NOP, _LDA, _BSR and _BOH).
(alpha_force_relocation): Likewise.
(alpha_fix_adjustable): Likewise. Add BFD_RELOC_16 case.
(tc_gen_reloc): Likewise. Add BFD_RELOC_ALPHA_LINKAGE for evax.
(emit_insn): New cases for evax specific relocs.
(assemble_insn): Fix indentation.
Take care of -MDISP in operand table.
* config/obj-evax.h (struct alpha_linkage_fixups): New struct.
(OBJ_SYMFIELD_TYPE): New macro.
(obj_symbol_new_hook): Define.
(obj_frob_symbol, obj_frob_file_before_adjust): Ditto.
(obj_frob_file_before_fix): Ditto.
(PDSC_S_M_HANDLER_VALID): New macro.
(PDSC_S_M_HANDLER_DATA_VALID): Ditto.
(TC_IMPLICIT_LCOMM_ALIGNMENT): Remove.
Add prototypes for functions declared in obj-evax.c
* config/obj-evax.c: Include subsegs.h, struc-symbol.h, safe-ctype.h.
(s_evax_weak): Convert to ansi-C.
(evax_symbol_new_hook): New function.
(evax_frob_symbol): Ditto.
(evax_frob_file_before_adjust): Ditto.
(evax_frob_file_before_fix): Ditto.
(evax_shorten_name): Ditto.
(crc32): Ditto.
(encode_32): Ditto.
(encode_16): Ditto.
(decode_16): Ditto.
(shorten_identifier): Ditto.
(is_truncated_identifier): Ditto.
* dwarf2dbg.c (out_debug_info): Do not append trailing slash on VMS.
* as.c (close_output_file): Remove #ifndef OBJ_VMS.
(main): Ditto.
Diffstat (limited to 'gas/config/obj-evax.c')
-rw-r--r-- | gas/config/obj-evax.c | 450 |
1 files changed, 442 insertions, 8 deletions
diff --git a/gas/config/obj-evax.c b/gas/config/obj-evax.c index a0cbae2..eb50283 100644 --- a/gas/config/obj-evax.c +++ b/gas/config/obj-evax.c @@ -2,6 +2,7 @@ Copyright 1996, 1997, 2007, 2008 Free Software Foundation, Inc. Contributed by Klaus Kämpf (kkaempf@progis.de) of proGIS Software, Aachen, Germany. + Extensively enhanced by Douglas Rupp of AdaCore. This file is part of GAS, the GNU Assembler @@ -22,9 +23,18 @@ #define OBJ_HEADER "obj-evax.h" +#include "bfd.h" +#include "vms.h" #include "as.h" +#include "subsegs.h" +#include "struc-symbol.h" +#include "safe-ctype.h" static void s_evax_weak (int); +static unsigned int crc32 (unsigned char *, int); +static char *encode_32 (unsigned int); +static char *encode_16 (unsigned int); +static int decode_16 (const char *); const pseudo_typeS obj_pseudo_table[] = { @@ -37,8 +47,7 @@ void obj_read_begin_hook () {} /* Handle the weak specific pseudo-op. */ static void -s_evax_weak (ignore) - int ignore; +s_evax_weak (int ignore ATTRIBUTE_UNUSED) { char *name; int c; @@ -73,11 +82,436 @@ s_evax_weak (ignore) demand_empty_rest_of_line (); } -/* - * Local Variables: - * comment-column: 0 - * fill-column: 131 - * End: - */ +void +evax_symbol_new_hook (symbolS *sym) +{ + struct evax_private_udata_struct *udata; + + udata = (struct evax_private_udata_struct *) + xmalloc (sizeof (struct evax_private_udata_struct)); + + udata->bsym = symbol_get_bfdsym (sym); + udata->enbsym = NULL; + udata->origname = xstrdup (S_GET_NAME (sym)); + udata->lkindex = 0; + symbol_get_bfdsym(sym)->udata.p = (PTR) udata; +} + +void +evax_frob_symbol (symbolS *sym, int *punt) +{ + const char *symname = S_GET_NAME (sym); + int symlen = strlen (symname); + asymbol *symbol = symbol_get_bfdsym (sym); + + if (symlen > 4 + && strcmp (symname + symlen - 4, "..en") == 0 + && S_GET_SEGMENT (sym) == undefined_section) + { + symbol_clear_used_in_reloc (sym); + *punt = 1; + } + + else if ((symbol->flags & BSF_GLOBAL) && (symbol->flags & BSF_FUNCTION)) + { + struct evax_private_udata_struct *udata + = (struct evax_private_udata_struct *)symbol->udata.p; + + /* Fix up equates of function definitions. */ + while (udata->enbsym == NULL) + { + /* ??? Equates have been resolved at this point so their + expression is O_constant; but they previously were + O_symbol and we hope the equated symbol is still there. */ + sym = symbol_get_value_expression (sym)->X_add_symbol; + if (sym == NULL) + abort (); + symbol = symbol_get_bfdsym (sym); + udata->enbsym + = ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym; + } + } +} + +void +evax_frob_file_before_adjust (void) +{ + struct alpha_linkage_fixups *l; + segT current_section = now_seg; + int current_subsec = now_subseg; + segment_info_type *seginfo; + int linkage_index = 1; + + subseg_set (alpha_link_section, 0); + seginfo = seg_info (alpha_link_section); + + for (l = alpha_linkage_fixup_root; l != NULL; l = l->next) + { + if (S_GET_SEGMENT (l->fixp->fx_addsy) == alpha_link_section) + { + symbolS * entry_sym; + fixS *fixpentry, *fixppdesc, *fixtail; + + fixtail = seginfo->fix_tail; + + /* Replace the linkage with the local symbols */ + entry_sym = symbol_find + (((struct evax_private_udata_struct *)symbol_get_bfdsym (l->fixp->fx_addsy)->udata.p)->enbsym->name); + if (!entry_sym) + abort (); + fixpentry = fix_new (l->fixp->fx_frag, l->fixp->fx_where, 8, + entry_sym, l->fixp->fx_offset, 0, + BFD_RELOC_64); + fixppdesc = fix_new (l->fixp->fx_frag, l->fixp->fx_where+8, 8, + l->fixp->fx_addsy, l->fixp->fx_offset, 0, + BFD_RELOC_64); + l->fixp->fx_size = 0; + l->fixp->fx_done = 1; + + /* If not already at the tail, splice the new fixups into + the chain right after the one we are nulling out */ + if (fixtail != l->fixp) + { + fixppdesc->fx_next = l->fixp->fx_next; + l->fixp->fx_next = fixpentry; + fixtail->fx_next = 0; + seginfo->fix_tail = fixtail; + } + } + else + { + ((struct evax_private_udata_struct *) + symbol_get_bfdsym (l->label)->udata.p)->lkindex = linkage_index; + + l->fixp->fx_addnumber = linkage_index; + + linkage_index += 2; + } + } + + subseg_set (current_section, current_subsec); +} + +void +evax_frob_file_before_fix (void) +{ + /* Now that the fixups are done earlier, we need to transfer the values + into the BFD symbols before calling fix_segment (ideally should not + be done also later). */ + if (symbol_rootP) + { + symbolS *symp; + + /* Set the value into the BFD symbol. Up til now the value + has only been kept in the gas symbolS struct. */ + for (symp = symbol_rootP; symp; symp = symbol_next (symp)) + symbol_get_bfdsym (symp)->value = S_GET_VALUE (symp); + } +} + +/* The length is computed from the maximum allowable length of 64 less the + 4 character ..xx extension that must be preserved (removed before + krunching and appended back on afterwards). The $<nnn>.. prefix is + also removed and prepened back on, but doesn't enter into the length + computation because symbols with that prefix are always resolved + by the assembler and will never appear in the symbol table. At least + I hope that's true, TBD. */ +#define MAX_LABEL_LENGTH 60 + +static char *shorten_identifier (char *); +static int is_truncated_identifier (char *); + +char * +evax_shorten_name (char *id) +{ + int prefix_dotdot = 0; + char prefix [64]; + int len = strlen (id); + int suffix_dotdot = len; + char suffix [64]; + char *base_id; + + /* This test may be too conservative. */ + if (len <= MAX_LABEL_LENGTH) + return id; + + suffix [0] = 0; + prefix [0] = 0; + + /* Check for ..xx suffix and save it. */ + if (strncmp (&id[len-4], "..", 2) == 0) + { + suffix_dotdot = len - 4; + strncpy (suffix, &id[len-4], 4); + suffix [4] = 0; + } + + /* Check for $<nnn>.. prefix and save it. */ + if ((id[0] == '$') && ISDIGIT (id[1])) + { + int i; + + for (i=2; i < len; i++) + { + if (!ISDIGIT (id[i])) + { + if (id[i] == '.' && id [i+1] == '.') + { + prefix_dotdot = i+2; + strncpy (prefix, id, prefix_dotdot); + prefix [prefix_dotdot] = 0; + } + break; + } + } + } + + /* We only need worry about krunching the base symbol. */ + base_id = xmalloc (suffix_dotdot - prefix_dotdot + 1); + strncpy (base_id, &id[prefix_dotdot], suffix_dotdot - prefix_dotdot); + base_id [suffix_dotdot - prefix_dotdot] = 0; + + if (strlen (base_id) > MAX_LABEL_LENGTH) + { + char new_id [4096]; + char *return_id; + + strcpy (new_id, base_id); + + /* Shorten it. */ + strcpy (new_id, shorten_identifier (new_id)); + + /* Prepend back the prefix if there was one. */ + if (prefix_dotdot) + { + memmove (&new_id [prefix_dotdot], new_id, strlen (new_id) + 1); + strncpy (new_id, prefix, prefix_dotdot); + } + + /* Append back the suffix if there was one. */ + if (strlen (suffix)) + strcat (new_id, suffix); + + /* Save it on the heap and return. */ + return_id = xmalloc (strlen (new_id) + 1); + strcpy (return_id, new_id); + + return return_id; + } + else + return id; +} + +/* The code below implements a mechanism for truncating long + identifiers to an arbitrary length (set by MAX_LABEL_LENGTH). + + It attempts to make each truncated identifier unique by replacing + part of the identifier with an encoded 32-bit CRC and an associated + checksum (the checksum is used as a way to determine that the name + was truncated). + + Note that both a portion of the start and of the end of the + identifier may be kept. The macro ID_SUFFIX_LENGTH will return the + number of characters in the suffix of the identifier that should be + kept. + + The portion of the identifier that is going to be removed is + checksummed. The checksum is then encoded as a 5-character string, + the characters of which are then summed. This sum is then encoded + as a 3-character string. Finally, the original length of the + identifier is encoded as a 3-character string. + + These three strings are then concatenated together (along with an _h + which further designates that the name was truncated): + + "original_identifier"_haaaaabbbccc + + aaaaa = 32-bit CRC + bbb = length of original identifier + ccc = sum of 32-bit CRC characters + + The resulting identifier will be MAX_LABEL_LENGTH characters long. + + */ + + +/* Table used to convert an integer into a string. */ + +static const char codings[] = { + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_'}; + +/* The number of codings in the above table. */ +static const int number_of_codings = sizeof (codings) / sizeof (char); + +/* Table used by decode_16 () to convert an encoded string back into + an integer. */ +static char decodings[256]; + +/* Table used by the crc32 function to calcuate the checksum. */ +static unsigned int crc32_table[256] = {0, 0}; + +/* Given a string in BUF, calculate a 32-bit CRC for it. + + This is used as a reasonably unique hash for the given string. */ + +static unsigned int +crc32 (unsigned char *buf, int len) +{ + unsigned int crc = 0xffffffff; + + if (! crc32_table[1]) + { + /* Initialize the CRC table and the decoding table. */ + int i, j; + unsigned int c; + + for (i = 0; i < 256; i++) + { + for (c = i << 24, j = 8; j > 0; --j) + c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1); + crc32_table[i] = c; + decodings[i] = 0; + } + for (i = 0; i < number_of_codings; i++) + decodings[codings[i] & 255] = i; + } + + while (len--) + { + crc = (crc << 8) ^ crc32_table[(crc >> 24) ^ *buf]; + buf++; + } + return crc; +} + +/* Encode the lower 32 bits of VALUE as a 5-character string. */ + +static char * +encode_32 (unsigned int value) +{ + static char res[6]; + int x; + + res[5] = 0; + for(x = 0; x < 5; x++) + { + res[x] = codings[value % number_of_codings]; + value = value / number_of_codings; + } + return res; +} + +/* Encode the lower 16 bits of VALUE as a 3-character string. */ + +static char * +encode_16 (unsigned int value) +{ + static char res[4]; + int x; + + res[3] = 0; + for(x = 0; x < 3; x++) + { + res[x] = codings[value % number_of_codings]; + value = value / number_of_codings; + } + return res; +} + +/* Convert the encoded string obtained from encode_16 () back into a + 16-bit integer. */ + +static int +decode_16 (const char *string) +{ + return decodings[(int) string[2]] * number_of_codings * number_of_codings + + decodings[(int) string[1]] * number_of_codings + + decodings[(int) string[0]]; +} + +/* ID_SUFFIX_LENGTH is used to determine how many characters in the + suffix of the identifier are to be preserved, if any. */ + +#ifndef ID_SUFFIX_LENGTH +#define ID_SUFFIX_LENGTH(ID) (0) +#endif + +/* Return a reasonably-unique version of NAME that is less than or + equal to MAX_LABEL_LENGTH characters long. The string returned from + this function may be a copy of NAME; the function will never + actually modify the contents of NAME. */ + +static char newname[MAX_LABEL_LENGTH + 1]; + +static char * +shorten_identifier (char *name) +{ + int crc, len, sum, x, final_len; + char *crc_chars; + int suffix_length = ID_SUFFIX_LENGTH (name); + + if ((len = strlen (name)) <= MAX_LABEL_LENGTH) + return name; + + final_len = MAX_LABEL_LENGTH - 2 - 5 - 3 - 3 - suffix_length; + crc = crc32 ((unsigned char *)name + final_len, + len - final_len - suffix_length); + crc_chars = encode_32 (crc); + sum = 0; + for (x = 0; x < 5; x++) + sum += crc_chars [x]; + strncpy (newname, name, final_len); + newname [MAX_LABEL_LENGTH] = 0; + /* Now append the suffix of the original identifier, if any. */ + if (suffix_length) + strncpy (newname + MAX_LABEL_LENGTH - suffix_length, + name + len - suffix_length, + suffix_length); + strncpy (newname + final_len, "_h", 2); + strncpy (newname + final_len + 2 , crc_chars, 5); + strncpy (newname + final_len + 2 + 5, encode_16 (len), 3); + strncpy (newname + final_len + 2 + 5 + 3, encode_16 (sum), 3); + if (!is_truncated_identifier (newname)) + abort (); + return newname; +} + +/* Determine whether or not ID is a truncated identifier, and return a + non-zero value if it is. */ + +static int +is_truncated_identifier (char *id) +{ + char *ptr; + int len = strlen (id); + /* If it's not exactly MAX_LABEL_LENGTH characters long, it can't be + a truncated identifier. */ + if (len != MAX_LABEL_LENGTH) + return 0; + + /* Start scanning backwards for a _h. */ + len = len - 3 - 3 - 5 - 2; + ptr = id + len; + while (ptr >= id) + { + if (ptr[0] == '_' && ptr[1] == 'h') + { + /* Now see if the sum encoded in the identifer matches. */ + int x, sum; + sum = 0; + for (x = 0; x < 5; x++) + sum += ptr[x + 2]; + /* If it matches, this is probably a truncated identifier. */ + if (sum == decode_16 (ptr + 5 + 2 + 3)) + return 1; + } + ptr--; + } + return 0; +} /* end of obj-evax.c */ |