/* .eh_frame section optimization.
- Copyright 2001, 2002 Free Software Foundation, Inc.
+ Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
Written by Jakub Jelinek <jakub@redhat.com>.
This file is part of BFD, the Binary File Descriptor library.
static int get_DW_EH_PE_width
PARAMS ((int, int));
static bfd_vma read_value
- PARAMS ((bfd *, bfd_byte *, int));
+ PARAMS ((bfd *, bfd_byte *, int, int));
static void write_value
PARAMS ((bfd *, bfd_byte *, bfd_vma, int));
static int cie_compare
return 0;
}
+#define get_DW_EH_PE_signed(encoding) (((encoding) & DW_EH_PE_signed) != 0)
+
/* Read a width sized value from memory. */
static bfd_vma
-read_value (abfd, buf, width)
+read_value (abfd, buf, width, is_signed)
bfd *abfd;
bfd_byte *buf;
int width;
+ int is_signed;
{
bfd_vma value;
switch (width)
{
- case 2: value = bfd_get_16 (abfd, buf); break;
- case 4: value = bfd_get_32 (abfd, buf); break;
- case 8: value = bfd_get_64 (abfd, buf); break;
- default: BFD_FAIL (); return 0;
+ case 2:
+ if (is_signed)
+ value = bfd_get_signed_16 (abfd, buf);
+ else
+ value = bfd_get_16 (abfd, buf);
+ break;
+ case 4:
+ if (is_signed)
+ value = bfd_get_signed_32 (abfd, buf);
+ else
+ value = bfd_get_32 (abfd, buf);
+ break;
+ case 8:
+ if (is_signed)
+ value = bfd_get_signed_64 (abfd, buf);
+ else
+ value = bfd_get_64 (abfd, buf);
+ break;
+ default:
+ BFD_FAIL ();
+ return 0;
}
return value;
}
-
+
/* Store a width sized value to memory. */
static void
/* This function is called for each input file before the .eh_frame
section is relocated. It discards duplicate CIEs and FDEs for discarded
- functions. The function returns true iff any entries have been
+ functions. The function returns TRUE iff any entries have been
deleted. */
-boolean
+bfd_boolean
_bfd_elf_discard_section_eh_frame (abfd, info, sec,
reloc_symbol_deleted_p, cookie)
bfd *abfd;
struct bfd_link_info *info;
asection *sec;
- boolean (*reloc_symbol_deleted_p) PARAMS ((bfd_vma, PTR));
+ bfd_boolean (*reloc_symbol_deleted_p) PARAMS ((bfd_vma, PTR));
struct elf_reloc_cookie *cookie;
{
bfd_byte *ehbuf = NULL, *buf;
if (sec->_raw_size == 0)
{
/* This file does not contain .eh_frame information. */
- return false;
+ return FALSE;
}
if ((sec->output_section != NULL
{
/* At least one of the sections is being discarded from the
link, so we should just ignore them. */
- return false;
+ return FALSE;
}
htab = elf_hash_table (info);
{
/* Empty .eh_frame section. */
free (ehbuf);
- return false;
+ return FALSE;
}
/* If .eh_frame section size doesn't fit into int, we cannot handle
which we cannot turn into PC relative,
don't create the binary search table,
since it is affected by runtime relocations. */
- hdr_info->table = false;
+ hdr_info->table = FALSE;
}
cie_usage_count++;
hdr_info->fde_count++;
}
elf_section_data (sec)->sec_info = sec_info;
- elf_section_data (sec)->sec_info_type = ELF_INFO_TYPE_EH_FRAME;
+ sec->sec_info_type = ELF_INFO_TYPE_EH_FRAME;
/* Ok, now we can assign new offsets. */
offset = 0;
free (ehbuf);
if (sec_info)
free (sec_info);
- hdr_info->table = false;
+ hdr_info->table = FALSE;
hdr_info->last_cie.hdr.length = 0;
- return false;
+ return FALSE;
}
/* This function is called for .eh_frame_hdr section after
_bfd_elf_discard_section_eh_frame has been called on all .eh_frame
input sections. It finalizes the size of .eh_frame_hdr section. */
-boolean
+bfd_boolean
_bfd_elf_discard_section_eh_frame_hdr (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
hdr_info = &htab->eh_info;
sec = hdr_info->hdr_sec;
if (sec == NULL)
- return false;
+ return FALSE;
sec->_cooked_size = EH_FRAME_HDR_SIZE;
if (hdr_info->table)
/* Request program headers to be recalculated. */
elf_tdata (abfd)->program_header_size = 0;
elf_tdata (abfd)->eh_frame_hdr = sec;
- return true;
+ return TRUE;
}
/* This function is called from size_dynamic_sections.
because later on it is too late for calling _bfd_strip_section_from_output,
since dynamic symbol table has been sized. */
-boolean
+bfd_boolean
_bfd_elf_maybe_strip_eh_frame_hdr (info)
struct bfd_link_info *info;
{
htab = elf_hash_table (info);
hdr_info = &htab->eh_info;
if (hdr_info->hdr_sec == NULL)
- return true;
+ return TRUE;
if (bfd_is_abs_section (hdr_info->hdr_sec->output_section))
{
hdr_info->hdr_sec = NULL;
- return true;
+ return TRUE;
}
abfd = NULL;
{
_bfd_strip_section_from_output (info, hdr_info->hdr_sec);
hdr_info->hdr_sec = NULL;
- return true;
+ return TRUE;
}
- hdr_info->table = true;
- return true;
+ hdr_info->table = TRUE;
+ return TRUE;
}
/* Adjust an address in the .eh_frame section. Given OFFSET within
struct eh_frame_sec_info *sec_info;
unsigned int lo, hi, mid;
- if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
+ if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
return offset;
sec_info = (struct eh_frame_sec_info *)
elf_section_data (sec)->sec_info;
/* Write out .eh_frame section. This is called with the relocated
contents. */
-boolean
+bfd_boolean
_bfd_elf_write_section_eh_frame (abfd, info, sec, contents)
bfd *abfd;
struct bfd_link_info *info;
ptr_size = (elf_elfheader (sec->owner)->e_ident[EI_CLASS]
== ELFCLASS64) ? 8 : 4;
- if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
+ if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
return bfd_set_section_contents (abfd, sec->output_section,
contents,
(file_ptr) sec->output_offset,
{
bfd_vma value;
- value = read_value (abfd, buf, per_width);
+ value = read_value (abfd, buf, per_width,
+ get_DW_EH_PE_signed
+ (per_encoding));
value += (sec_info->entry[i].offset
- sec_info->entry[i].new_offset);
write_value (abfd, buf, value, per_width);
unsigned int width;
buf = contents + sec_info->entry[i].offset;
- /* Skip length. */
+ /* Skip length. */
buf += 4;
bfd_put_32 (abfd,
sec_info->entry[i].new_offset + 4 - cie_offset, buf);
buf += 4;
width = get_DW_EH_PE_width (sec_info->entry[i].fde_encoding,
ptr_size);
- address = value = read_value (abfd, buf, width);
+ address = value = read_value (abfd, buf, width,
+ get_DW_EH_PE_signed
+ (sec_info->entry[i].fde_encoding));
if (value)
{
switch (sec_info->entry[i].fde_encoding & 0xf0)
buf += sec_info->entry[i].lsda_offset;
width = get_DW_EH_PE_width (sec_info->entry[i].lsda_encoding,
ptr_size);
- value = read_value (abfd, buf, width);
+ value = read_value (abfd, buf, width,
+ get_DW_EH_PE_signed
+ (sec_info->entry[i].lsda_encoding));
if (value)
{
if ((sec_info->entry[i].lsda_encoding & 0xf0)
FDE initial_location field and FDE address,
sorted by increasing initial_loc) */
-boolean
+bfd_boolean
_bfd_elf_write_section_eh_frame_hdr (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
hdr_info = &htab->eh_info;
sec = hdr_info->hdr_sec;
if (sec == NULL)
- return true;
+ return TRUE;
size = EH_FRAME_HDR_SIZE;
if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
size += 4 + hdr_info->fde_count * 8;
contents = bfd_malloc (size);
if (contents == NULL)
- return false;
+ return FALSE;
eh_frame_sec = bfd_get_section_by_name (abfd, ".eh_frame");
if (eh_frame_sec == NULL)
- return false;
+ return FALSE;
memset (contents, 0, EH_FRAME_HDR_SIZE);
contents[0] = 1; /* Version */