static bfd_boolean read_section_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount, void *dhandle, bfd_boolean *pfound) { static struct { const char *secname; const char *strsecname; } names[] = { { ".stab", ".stabstr" }, { "LC_SYMTAB.stabs", "LC_SYMTAB.stabstr" }, { "$GDB_SYMBOLS$", "$GDB_STRINGS$" } }; unsigned int i; void *shandle; *pfound = FALSE; shandle = NULL; for (i = 0; i < sizeof names / sizeof names[0]; i++) { asection *sec, *strsec; sec = bfd_get_section_by_name (abfd, names[i].secname); strsec = bfd_get_section_by_name (abfd, names[i].strsecname); if (sec != NULL && strsec != NULL) { bfd_size_type stabsize, strsize; bfd_byte *stabs, *strings; bfd_byte *stab; bfd_size_type stroff, next_stroff; stabsize = bfd_section_size (abfd, sec); stabs = (bfd_byte *) xmalloc (stabsize); if (! bfd_get_section_contents (abfd, sec, stabs, 0, stabsize)) { fprintf (stderr, "%s: %s: %s\n", bfd_get_filename (abfd), names[i].secname, bfd_errmsg (bfd_get_error ())); return FALSE; } strsize = bfd_section_size (abfd, strsec); strings = (bfd_byte *) xmalloc (strsize + 1); if (! bfd_get_section_contents (abfd, strsec, strings, 0, strsize)) { fprintf (stderr, "%s: %s: %s\n", bfd_get_filename (abfd), names[i].strsecname, bfd_errmsg (bfd_get_error ())); return FALSE; } /* Zero terminate the strings table, just in case. */ strings [strsize] = 0; if (shandle == NULL) { shandle = start_stab (dhandle, abfd, TRUE, syms, symcount); if (shandle == NULL) return FALSE; } *pfound = TRUE; stroff = 0; next_stroff = 0; /* PR 17512: file: 078-60391-0.001:0.1. */ for (stab = stabs; stab <= (stabs + stabsize) - 12; stab += 12) { unsigned int strx; int type; int other ATTRIBUTE_UNUSED; int desc; bfd_vma value; /* This code presumes 32 bit values. */ strx = bfd_get_32 (abfd, stab); type = bfd_get_8 (abfd, stab + 4); other = bfd_get_8 (abfd, stab + 5); desc = bfd_get_16 (abfd, stab + 6); value = bfd_get_32 (abfd, stab + 8); if (type == 0) { /* Special type 0 stabs indicate the offset to the next string table. */ stroff = next_stroff; next_stroff += value; } else { size_t len; char *f, *s; if (stroff + strx >= strsize) { fprintf (stderr, _("%s: %s: stab entry %ld is corrupt, strx = 0x%x, type = %d\n"), bfd_get_filename (abfd), names[i].secname, (long) (stab - stabs) / 12, strx, type); continue; } s = (char *) strings + stroff + strx; f = NULL; /* PR 17512: file: 002-87578-0.001:0.1. It is possible to craft a file where, without the 'strlen (s) > 0', an attempt to read the byte before 'strings' would occur. */ while ((len = strlen (s)) > 0 && s[len - 1] == '\\' && stab + 12 < stabs + stabsize) { char *p; stab += 12; p = s + len - 1; *p = '\0'; strx = stroff + bfd_get_32 (abfd, stab); if (strx >= strsize) { fprintf (stderr, _("%s: %s: stab entry %ld is corrupt\n"), bfd_get_filename (abfd), names[i].secname, (long) (stab - stabs) / 12); break; } else s = concat (s, (char *) strings + strx, (const char *) NULL); /* We have to restore the backslash, because, if the linker is hashing stabs strings, we may see the same string more than once. */ *p = '\\'; if (f != NULL) free (f); f = s; } save_stab (type, desc, value, s); if (! parse_stab (dhandle, shandle, type, desc, value, s)) { stab_context (); free_saved_stabs (); return FALSE; } /* Don't free f, since I think the stabs code expects strings to hang around. This should be straightened out. FIXME. */ } } free_saved_stabs (); free (stabs); /* Don't free strings, since I think the stabs code expects the strings to hang around. This should be straightened out. FIXME. */ } } if (shandle != NULL) { if (! finish_stab (dhandle, shandle)) return FALSE; } return TRUE; }
static void extra_case (bfd *in_abfd, struct bfd_link_info *link_info, struct bfd_link_order *link_order, arelent *reloc, bfd_byte *data, unsigned int *src_ptr, unsigned int *dst_ptr) { asection * input_section = link_order->u.indirect.section; switch (reloc->howto->type) { case R_IMM8: bfd_put_8 (in_abfd, bfd_coff_reloc16_get_value (reloc, link_info, input_section), data + *dst_ptr); (*dst_ptr) += 1; (*src_ptr) += 1; break; case R_IMM32: /* If no flags are set, assume immediate value. */ if (! (*reloc->sym_ptr_ptr)->section->flags) { bfd_put_32 (in_abfd, bfd_coff_reloc16_get_value (reloc, link_info, input_section), data + *dst_ptr); } else { bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info, input_section); /* Addresses are 23 bit, and the layout of those in a 32-bit value is as follows: 1AAAAAAA xxxxxxxx AAAAAAAA AAAAAAAA (A - address bits, x - ignore). */ dst = (dst & 0xffff) | ((dst & 0xff0000) << 8) | 0x80000000; bfd_put_32 (in_abfd, dst, data + *dst_ptr); } (*dst_ptr) += 4; (*src_ptr) += 4; break; case R_IMM4L: bfd_put_8 (in_abfd, ((bfd_get_8 (in_abfd, data + *dst_ptr) & 0xf0) | (0x0f & bfd_coff_reloc16_get_value (reloc, link_info, input_section))), data + *dst_ptr); (*dst_ptr) += 1; (*src_ptr) += 1; break; case R_IMM16: bfd_put_16 (in_abfd, bfd_coff_reloc16_get_value (reloc, link_info, input_section), data + *dst_ptr); (*dst_ptr) += 2; (*src_ptr) += 2; break; case R_JR: { bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info, input_section); bfd_vma dot = (link_order->offset + *dst_ptr + input_section->output_section->vma); /* -1L, since we are in the odd byte of the word, and the pc has been * incremented: */ ptrdiff_t gap = ((ptrdiff_t)(dst - dot) - 1L); if (gap & 1L) abort(); gap /= 2L; if ((gap > 128L) || (gap < -128L)) { if (!((*link_info->callbacks->reloc_overflow) (link_info, NULL, bfd_asymbol_name(*reloc->sym_ptr_ptr), reloc->howto->name, reloc->addend, input_section->owner, input_section, reloc->address))) abort(); } bfd_put_8(in_abfd, gap, (data + *dst_ptr)); (*dst_ptr)++; (*src_ptr)++; break; } case R_DISP7: { bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info, input_section); bfd_vma dot = (link_order->offset + *dst_ptr + input_section->output_section->vma); /* -1L, since we are in the odd byte of the word, and the pc has been * incremented: */ ptrdiff_t gap = ((ptrdiff_t)(dst - dot) - 1L); if (gap & 1L) abort(); gap /= 2L; if ((gap > 0L) || (gap < -127L)) { if (!((*link_info->callbacks->reloc_overflow) (link_info, NULL, bfd_asymbol_name(*reloc->sym_ptr_ptr), reloc->howto->name, reloc->addend, input_section->owner, input_section, reloc->address))) abort(); } bfd_put_8(in_abfd, (bfd_get_8(in_abfd, data + *dst_ptr) & 0x80) + (-gap & 0x7f), (data + *dst_ptr)); (*dst_ptr)++; (*src_ptr)++; break; } case R_CALLR: { bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info, input_section); bfd_vma dot = (link_order->offset + *dst_ptr + input_section->output_section->vma); ptrdiff_t gap = ((ptrdiff_t)(dst - dot) - 2L); if (gap & 1L) abort(); if ((gap > 4096L) || (gap < -4095L)) { if (!((*link_info->callbacks->reloc_overflow) (link_info, NULL, bfd_asymbol_name(*reloc->sym_ptr_ptr), reloc->howto->name, reloc->addend, input_section->owner, input_section, reloc->address))) abort(); } gap /= 2L; bfd_put_16(in_abfd, ((bfd_get_16(in_abfd, (data + *dst_ptr)) & 0xf000) | (-gap & 0x0fff)), (data + *dst_ptr)); (*dst_ptr) += 2; (*src_ptr) += 2; break; } case R_REL16: { bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info, input_section); bfd_vma dot = (link_order->offset + *dst_ptr + input_section->output_section->vma); ptrdiff_t gap = ((ptrdiff_t)(dst - dot) - 2L); if ((gap > 32767L) || (gap < -32768L)) { if (!((*link_info->callbacks->reloc_overflow) (link_info, NULL, bfd_asymbol_name(*reloc->sym_ptr_ptr), reloc->howto->name, reloc->addend, input_section->owner, input_section, reloc->address))) abort(); } bfd_put_16(in_abfd, (bfd_vma)gap, (data + *dst_ptr)); (*dst_ptr) += 2; (*src_ptr) += 2; break; } default: abort(); } }
useless for a relocation, so we just get the offset value and place a version of this within the object code. tic30_aout_final_link_relocate will then calculate the required relocation to add on to the value in the object code. */ static bfd_reloc_status_type tic30_aout_fix_pcrel_16 (bfd *abfd, arelent *reloc_entry, asymbol *symbol ATTRIBUTE_UNUSED, void * data, asection *input_section ATTRIBUTE_UNUSED, bfd *output_bfd ATTRIBUTE_UNUSED, char **error_message ATTRIBUTE_UNUSED) { bfd_vma relocation = 1; bfd_byte offset_data = bfd_get_8 (abfd, (bfd_byte *) data + reloc_entry->address - 1); /* The byte before the location of the fix contains bits 23-16 of the pcrel instruction. Bit 21 is set for a delayed instruction which requires on offset of 3 instead of 1. */ if (offset_data & 0x20) relocation -= 3; else relocation -= 1; bfd_put_16 (abfd, relocation, (bfd_byte *) data + reloc_entry->address); return bfd_reloc_ok; } /* This function is used as a callback for 16-bit relocs. This is required for relocations between segments. A line in aoutx.h requires that any relocations for the data section should point to
static bfd_boolean read_section_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount, void *dhandle, bfd_boolean *pfound) { static struct { const char *secname; const char *strsecname; } names[] = { { ".stab", ".stabstr" }, { "LC_SYMTAB.stabs", "LC_SYMTAB.stabstr" } }; unsigned int i; void *shandle; *pfound = FALSE; shandle = NULL; for (i = 0; i < sizeof names / sizeof names[0]; i++) { asection *sec, *strsec; sec = bfd_get_section_by_name (abfd, names[i].secname); strsec = bfd_get_section_by_name (abfd, names[i].strsecname); if (sec != NULL && strsec != NULL) { bfd_size_type stabsize, strsize; bfd_byte *stabs, *strings; bfd_byte *stab; bfd_size_type stroff, next_stroff; stabsize = bfd_section_size (abfd, sec); stabs = (bfd_byte *) xmalloc (stabsize); if (! bfd_get_section_contents (abfd, sec, stabs, 0, stabsize)) { fprintf (stderr, "%s: %s: %s\n", bfd_get_filename (abfd), names[i].secname, bfd_errmsg (bfd_get_error ())); return FALSE; } strsize = bfd_section_size (abfd, strsec); strings = (bfd_byte *) xmalloc (strsize); if (! bfd_get_section_contents (abfd, strsec, strings, 0, strsize)) { fprintf (stderr, "%s: %s: %s\n", bfd_get_filename (abfd), names[i].strsecname, bfd_errmsg (bfd_get_error ())); return FALSE; } if (shandle == NULL) { shandle = start_stab (dhandle, abfd, TRUE, syms, symcount); if (shandle == NULL) return FALSE; } *pfound = TRUE; stroff = 0; next_stroff = 0; for (stab = stabs; stab < (stabs + stabsize); stab += 12) { unsigned int strx; int type; int other; int desc; bfd_vma value; /* This code presumes 32 bit values: */ strx = bfd_get_32(abfd, stab); type = bfd_get_8(abfd, stab + 4); other = bfd_get_8(abfd, stab + 5); desc = bfd_get_16(abfd, stab + 6); value = bfd_get_32(abfd, stab + 8); if (type == 0) { /* Special type 0 stabs indicate the offset to the next string table. */ stroff = next_stroff; next_stroff += value; } else { char *f, *s; f = NULL; if ((stroff + strx) > strsize) { fprintf(stderr, "%s: %s: stab entry %ld is corrupt, strx = 0x%x, type = %d, other = %d\n", bfd_get_filename(abfd), names[i].secname, (long)(stab - stabs) / 12, strx, type, other); continue; } s = (char *) strings + stroff + strx; while (s[strlen (s) - 1] == '\\' && stab + 12 < stabs + stabsize) { char *p; stab += 12; p = s + strlen (s) - 1; *p = '\0'; s = concat (s, ((char *) strings + stroff + bfd_get_32 (abfd, stab)), (const char *) NULL); /* We have to restore the backslash, because, if the linker is hashing stabs strings, we may see the same string more than once. */ *p = '\\'; if (f != NULL) free (f); f = s; } save_stab (type, desc, value, s); if (! parse_stab (dhandle, shandle, type, desc, value, s)) { stab_context (); free_saved_stabs (); return FALSE; } /* Don't free f, since I think the stabs code expects strings to hang around. This should be straightened out. FIXME. */ } } free_saved_stabs (); free (stabs); /* Don't free strings, since I think the stabs code expects the strings to hang around. This should be straightened out. FIXME. */ } } if (shandle != NULL) { if (! finish_stab (dhandle, shandle)) return FALSE; } return TRUE; }