Reimplement segment writing.
(elf_write_phdrs): Use precomputed e_phoff rather than making assumptions. (elf_build_phdrs): Disabled, for now. (assign_file_position_for_section): Don't change file offset for SHT_NOBITS. (assign_file_positions_for_symtab_and_strtabs): New function. (struct seg_info): New type. (map_program_segments): New function. (assign_file_positions_except_relocs): For executables, leave section headers &c for last, and properly align all sections with flag SHF_ALLOC set. (prep_headers): No longer abort when EXEC_P is set. (write_shdrs_and_ehdr): Deleted all code relating to program segments. (various): Deleted some unused code, and debugging "malloc(0)" calls. (write_relocs): Cache value of last symbol looked up, to save time if the symbol is referred to repeatedly. (elf_fake_sections): Check only SEC_RELOC flag, not number of relocs. (assign_section_numbers): Likewise.
This commit is contained in:
parent
08ecd8f3d8
commit
300adb3110
1 changed files with 345 additions and 118 deletions
463
bfd/elfcode.h
463
bfd/elfcode.h
|
@ -63,6 +63,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
#include "libbfd.h"
|
||||
#include "libelf.h"
|
||||
|
||||
#ifndef alloca
|
||||
PTR alloca ();
|
||||
#endif
|
||||
|
||||
/* Renaming structures, typedefs, macros and functions to be size-specific. */
|
||||
#define Elf_External_Ehdr NAME(Elf,External_Ehdr)
|
||||
#define Elf_External_Sym NAME(Elf,External_Sym)
|
||||
|
@ -671,7 +675,9 @@ DEFUN (elf_new_section_hook, (abfd, sec),
|
|||
AND asection *sec)
|
||||
{
|
||||
struct bfd_elf_section_data *sdata;
|
||||
sec->used_by_bfd = sdata = bfd_alloc (abfd, sizeof (*sdata));
|
||||
|
||||
sdata = (struct bfd_elf_section_data *) bfd_alloc (abfd, sizeof (*sdata));
|
||||
sec->used_by_bfd = (PTR) sdata;
|
||||
memset (sdata, 0, sizeof (*sdata));
|
||||
return true;
|
||||
}
|
||||
|
@ -893,7 +899,8 @@ DEFUN (elf_object_p, (abfd), bfd * abfd)
|
|||
goto wrong;
|
||||
i_shdrp = (Elf_Internal_Shdr *)
|
||||
bfd_alloc (abfd, sizeof (*i_shdrp) * i_ehdrp->e_shnum);
|
||||
elf_elfsections (abfd) = bfd_alloc (abfd, sizeof (i_shdrp) * i_ehdrp->e_shnum);
|
||||
elf_elfsections (abfd) =
|
||||
(Elf_Internal_Shdr **) bfd_alloc (abfd, sizeof (i_shdrp) * i_ehdrp->e_shnum);
|
||||
if (!i_shdrp || !elf_elfsections(abfd))
|
||||
{
|
||||
bfd_error = no_memory;
|
||||
|
@ -1076,12 +1083,7 @@ DEFUN (elf_make_sections, (abfd, asect, obj),
|
|||
this_hdr->sh_size = asect->_raw_size;
|
||||
/* contents already set by elf_set_section_contents */
|
||||
|
||||
if ((asect->flags & SEC_RELOC)
|
||||
#if 0
|
||||
/* The flags are sometimes inconsistent. */
|
||||
&& asect->reloc_count > 0
|
||||
#endif
|
||||
)
|
||||
if (asect->flags & SEC_RELOC)
|
||||
{
|
||||
/* emit a reloc section, and thus strtab and symtab... */
|
||||
Elf_Internal_Shdr *rela_hdr;
|
||||
|
@ -1135,8 +1137,9 @@ write_relocs (abfd, sec, xxx)
|
|||
Elf_External_Rel *outbound_relocs;
|
||||
int idx;
|
||||
int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
|
||||
asymbol *last_sym = 0;
|
||||
int last_sym_idx;
|
||||
|
||||
malloc(0);
|
||||
if ((sec->flags & SEC_RELOC) == 0)
|
||||
return;
|
||||
/* Flags are sometimes inconsistent. */
|
||||
|
@ -1149,81 +1152,77 @@ malloc(0);
|
|||
rela_hdr->contents = (void *) bfd_alloc (abfd, rela_hdr->sh_size);
|
||||
|
||||
/* orelocation has the data, reloc_count has the count... */
|
||||
if (use_rela_p)
|
||||
if (use_rela_p)
|
||||
{
|
||||
outbound_relocas = (Elf_External_Rela *) rela_hdr->contents;
|
||||
|
||||
for (idx = 0; idx < sec->reloc_count; idx++)
|
||||
{
|
||||
outbound_relocas = (Elf_External_Rela *) rela_hdr->contents;
|
||||
Elf_Internal_Rela dst_rela;
|
||||
Elf_External_Rela *src_rela;
|
||||
arelent *ptr;
|
||||
asymbol *sym;
|
||||
int n;
|
||||
|
||||
for (idx = 0; idx < sec->reloc_count; idx++)
|
||||
ptr = sec->orelocation[idx];
|
||||
src_rela = outbound_relocas + idx;
|
||||
if (!(abfd->flags & EXEC_P))
|
||||
dst_rela.r_offset = ptr->address - sec->vma;
|
||||
else
|
||||
dst_rela.r_offset = ptr->address;
|
||||
|
||||
sym = *ptr->sym_ptr_ptr;
|
||||
if (sym == last_sym)
|
||||
n = last_sym_idx;
|
||||
else
|
||||
{
|
||||
Elf_Internal_Rela dst_rela;
|
||||
Elf_External_Rela *src_rela;
|
||||
arelent *ptr;
|
||||
asymbol *sym;
|
||||
|
||||
ptr = sec->orelocation[idx];
|
||||
src_rela = outbound_relocas + idx;
|
||||
if (!(abfd->flags & EXEC_P))
|
||||
dst_rela.r_offset = ptr->address - sec->vma;
|
||||
else
|
||||
dst_rela.r_offset = ptr->address;
|
||||
|
||||
sym = *ptr->sym_ptr_ptr;
|
||||
#if 0
|
||||
/* I think this bit is wrong. But doing it right here means
|
||||
fixing bfd_perform_relocation, and verifying that it doesn't
|
||||
break other targets. Sigh.
|
||||
|
||||
Problem I'm trying to solve here: `ld -r' tends to get
|
||||
offset of target symbol in output-file section put into
|
||||
addend, but retains the original symbol, so the net
|
||||
result is doubling of that offset. */
|
||||
if (!bfd_is_com_section (sym->section)
|
||||
&& sym->section != &bfd_und_section)
|
||||
{
|
||||
/* Could adjust either the offset or the symbol here.
|
||||
I'm pretty indifferent. */
|
||||
sym = sym->section->symbol;
|
||||
}
|
||||
#endif
|
||||
dst_rela.r_info
|
||||
= ELF_R_INFO (elf_symbol_from_bfd_symbol (abfd, &sym),
|
||||
ptr->howto->type);
|
||||
|
||||
dst_rela.r_addend = ptr->addend;
|
||||
elf_swap_reloca_out (abfd, &dst_rela, src_rela);
|
||||
malloc(0);
|
||||
last_sym = sym;
|
||||
last_sym_idx = n = elf_symbol_from_bfd_symbol (abfd, &sym);
|
||||
}
|
||||
dst_rela.r_info = ELF_R_INFO (n, ptr->howto->type);
|
||||
|
||||
dst_rela.r_addend = ptr->addend;
|
||||
elf_swap_reloca_out (abfd, &dst_rela, src_rela);
|
||||
}
|
||||
else
|
||||
/* REL relocations */
|
||||
}
|
||||
else
|
||||
/* REL relocations */
|
||||
{
|
||||
outbound_relocs = (Elf_External_Rel *) rela_hdr->contents;
|
||||
|
||||
for (idx = 0; idx < sec->reloc_count; idx++)
|
||||
{
|
||||
outbound_relocs = (Elf_External_Rel *) rela_hdr->contents;
|
||||
Elf_Internal_Rel dst_rel;
|
||||
Elf_External_Rel *src_rel;
|
||||
arelent *ptr;
|
||||
int n;
|
||||
asymbol *sym;
|
||||
|
||||
for (idx = 0; idx < sec->reloc_count; idx++)
|
||||
ptr = sec->orelocation[idx];
|
||||
sym = *ptr->sym_ptr_ptr;
|
||||
src_rel = outbound_relocs + idx;
|
||||
if (!(abfd->flags & EXEC_P))
|
||||
dst_rel.r_offset = ptr->address - sec->vma;
|
||||
else
|
||||
dst_rel.r_offset = ptr->address;
|
||||
|
||||
if (sym == last_sym)
|
||||
n = last_sym_idx;
|
||||
else
|
||||
{
|
||||
Elf_Internal_Rel dst_rel;
|
||||
Elf_External_Rel *src_rel;
|
||||
arelent *ptr;
|
||||
|
||||
ptr = sec->orelocation[idx];
|
||||
src_rel = outbound_relocs + idx;
|
||||
if (!(abfd->flags & EXEC_P))
|
||||
dst_rel.r_offset = ptr->address - sec->vma;
|
||||
else
|
||||
dst_rel.r_offset = ptr->address;
|
||||
|
||||
dst_rel.r_info
|
||||
= ELF_R_INFO (elf_symbol_from_bfd_symbol (abfd, ptr->sym_ptr_ptr),
|
||||
ptr->howto->type);
|
||||
|
||||
elf_swap_reloc_out (abfd, &dst_rel, src_rel);
|
||||
|
||||
/* Update the addend -- FIXME add 64 bit support. */
|
||||
bfd_put_32 (abfd, ptr->addend,
|
||||
(unsigned char *) (elf_section_data (sec)->this_hdr.contents)
|
||||
+ dst_rel.r_offset);
|
||||
last_sym = sym;
|
||||
last_sym_idx = n = elf_symbol_from_bfd_symbol (abfd, &sym);
|
||||
}
|
||||
dst_rel.r_info = ELF_R_INFO (n, ptr->howto->type);
|
||||
|
||||
elf_swap_reloc_out (abfd, &dst_rel, src_rel);
|
||||
|
||||
/* Update the addend -- FIXME add 64 bit support. */
|
||||
bfd_put_32 (abfd, ptr->addend,
|
||||
(unsigned char *) (elf_section_data (sec)->this_hdr.contents)
|
||||
+ dst_rel.r_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1296,9 +1295,7 @@ DEFUN (elf_fake_sections, (abfd, asect, obj),
|
|||
/* Note that only one symtab is used, so just remember it
|
||||
for now. */
|
||||
|
||||
if ((asect->flags & SEC_RELOC)
|
||||
/* inconsistent flags... */
|
||||
&& asect->reloc_count > 0)
|
||||
if (asect->flags & SEC_RELOC)
|
||||
{
|
||||
int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
|
||||
|
||||
|
@ -1511,7 +1508,7 @@ DEFUN (elf_write_phdrs, (abfd, i_ehdrp, i_phdrp, phdr_cnt),
|
|||
Elf32_Half phdr_cnt)
|
||||
{
|
||||
/* first program header entry goes after the file header */
|
||||
int outbase = i_ehdrp->e_ehsize;
|
||||
int outbase = i_ehdrp->e_phoff;
|
||||
int i;
|
||||
Elf_External_Phdr x_phdr;
|
||||
|
||||
|
@ -1526,6 +1523,7 @@ DEFUN (elf_write_phdrs, (abfd, i_ehdrp, i_phdrp, phdr_cnt),
|
|||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static Elf_Internal_Phdr *
|
||||
DEFUN (elf_build_phdrs, (abfd, i_ehdrp, i_shdrp, phdr_cnt),
|
||||
bfd * abfd AND
|
||||
|
@ -1700,6 +1698,7 @@ DEFUN (elf_build_phdrs, (abfd, i_ehdrp, i_shdrp, phdr_cnt),
|
|||
|
||||
return phdr_buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const Elf_Internal_Shdr null_shdr;
|
||||
|
||||
|
@ -1733,7 +1732,7 @@ assign_section_numbers (abfd)
|
|||
{
|
||||
struct bfd_elf_section_data *d = elf_section_data (sec);
|
||||
d->this_idx = section_number++;
|
||||
if (sec->reloc_count != 0)
|
||||
if (sec->flags & SEC_RELOC)
|
||||
{
|
||||
d->rel_idx = section_number++;
|
||||
d->rel_hdr.sh_link = t->symtab_section;
|
||||
|
@ -1747,8 +1746,8 @@ assign_section_numbers (abfd)
|
|||
|
||||
/* Set up the list of section header pointers, in agreement with the
|
||||
indices. */
|
||||
i_shdrp = bfd_alloc (abfd,
|
||||
section_number * sizeof (Elf_Internal_Shdr *));
|
||||
i_shdrp = (Elf_Internal_Shdr **)
|
||||
bfd_alloc (abfd, section_number * sizeof (Elf_Internal_Shdr *));
|
||||
elf_elfsections(abfd) = i_shdrp;
|
||||
for (i = 0; i < section_number; i++)
|
||||
i_shdrp[i] = 0;
|
||||
|
@ -1779,10 +1778,196 @@ assign_file_position_for_section (i_shdrp, offset)
|
|||
file_ptr offset;
|
||||
{
|
||||
i_shdrp->sh_offset = offset;
|
||||
offset += i_shdrp->sh_size;
|
||||
if (i_shdrp->sh_type != SHT_NOBITS)
|
||||
offset += i_shdrp->sh_size;
|
||||
return offset;
|
||||
}
|
||||
|
||||
static INLINE file_ptr
|
||||
assign_file_positions_for_symtab_and_strtabs (abfd, off)
|
||||
bfd *abfd;
|
||||
file_ptr off;
|
||||
{
|
||||
struct elf_obj_tdata *t = elf_tdata (abfd);
|
||||
|
||||
off = assign_file_position_for_section (&t->shstrtab_hdr, off);
|
||||
off = assign_file_position_for_section (&t->symtab_hdr, off);
|
||||
off = assign_file_position_for_section (&t->strtab_hdr, off);
|
||||
return off;
|
||||
}
|
||||
|
||||
struct seg_info {
|
||||
bfd_vma low, mem_size;
|
||||
file_ptr file_size;
|
||||
int start_pos;
|
||||
int sh_flags;
|
||||
struct seg_info *next;
|
||||
};
|
||||
|
||||
static void
|
||||
map_program_segments (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
Elf_Internal_Shdr **i_shdrpp = elf_elfsections (abfd);
|
||||
Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
|
||||
Elf_Internal_Shdr *i_shdrp;
|
||||
Elf_Internal_Phdr *phdr;
|
||||
char *done;
|
||||
int i, n_left = 0;
|
||||
file_ptr lowest_offset = 0;
|
||||
struct seg_info *seg = 0;
|
||||
|
||||
done = alloca (i_ehdrp->e_shnum);
|
||||
memset (done, 0, i_ehdrp->e_shnum);
|
||||
for (i = 0; i < i_ehdrp->e_shnum; i++)
|
||||
{
|
||||
i_shdrp = i_shdrpp[i];
|
||||
/* If it's going to be mapped in, it's been assigned a position. */
|
||||
if (i_shdrp->sh_offset + 1 == 0)
|
||||
{
|
||||
/* Well, not really, but we won't process it here. */
|
||||
done[i] = 1;
|
||||
continue;
|
||||
}
|
||||
if (i_shdrp->sh_offset < lowest_offset
|
||||
|| lowest_offset == 0)
|
||||
lowest_offset = i_shdrp->sh_offset;
|
||||
/* Only interested in PROGBITS or NOBITS for generating segments. */
|
||||
switch (i_shdrp->sh_type)
|
||||
{
|
||||
case SHT_PROGBITS:
|
||||
case SHT_NOBITS:
|
||||
break;
|
||||
default:
|
||||
done[i] = 1;
|
||||
}
|
||||
if (!done[i])
|
||||
n_left++;
|
||||
}
|
||||
while (n_left)
|
||||
{
|
||||
bfd_vma lowest_vma = -1, high;
|
||||
int low_sec = 0;
|
||||
int mem_size;
|
||||
int file_size = 0;
|
||||
|
||||
for (i = 1; i < i_ehdrp->e_shnum; i++)
|
||||
{
|
||||
i_shdrp = i_shdrpp[i];
|
||||
if (!done[i] && i_shdrp->sh_addr < lowest_vma)
|
||||
{
|
||||
lowest_vma = i_shdrp->sh_addr;
|
||||
low_sec = i;
|
||||
}
|
||||
}
|
||||
if (low_sec == 0)
|
||||
abort ();
|
||||
/* So now we know the lowest vma of any unassigned sections; start
|
||||
a segment there. */
|
||||
{
|
||||
struct seg_info *s;
|
||||
s = (struct seg_info *) bfd_alloc (abfd, sizeof (struct seg_info));
|
||||
s->next = seg;
|
||||
seg = s;
|
||||
}
|
||||
seg->low = lowest_vma;
|
||||
i_shdrp = i_shdrpp[low_sec];
|
||||
seg->start_pos = i_shdrp->sh_offset;
|
||||
seg->sh_flags = i_shdrp->sh_flags;
|
||||
done[low_sec] = 1, n_left--;
|
||||
mem_size = i_shdrp->sh_size;
|
||||
high = lowest_vma + i_shdrp->sh_size;
|
||||
|
||||
if (i_shdrp->sh_type == SHT_PROGBITS)
|
||||
file_size = i_shdrp->sh_size;
|
||||
|
||||
for (i = 0; i < i_ehdrp->e_shnum; i++)
|
||||
{
|
||||
file_ptr f1;
|
||||
|
||||
if (file_size != mem_size)
|
||||
break;
|
||||
if (done[i])
|
||||
continue;
|
||||
i_shdrp = i_shdrpp[i];
|
||||
/* position of next byte on disk */
|
||||
f1 = seg->start_pos + file_size;
|
||||
if (i_shdrp->sh_type == SHT_PROGBITS)
|
||||
{
|
||||
if (i_shdrp->sh_offset - f1 != i_shdrp->sh_addr - high)
|
||||
continue;
|
||||
}
|
||||
else /* sh_type == NOBITS */
|
||||
{
|
||||
/* If the section in question has no contents in the disk
|
||||
file, we really don't care where it supposedly starts.
|
||||
But we don't want to bother merging it into this segment
|
||||
if it doesn't start on this memory page. */
|
||||
bfd_vma page1, page2;
|
||||
bfd_vma maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
|
||||
|
||||
/* page number in address space of current end of seg */
|
||||
page1 = (high - 1 + maxpagesize - 1) / maxpagesize;
|
||||
/* page number in address space of start of this section */
|
||||
page2 = (i_shdrp->sh_addr + maxpagesize - 1) / maxpagesize;
|
||||
|
||||
if (page1 != page2)
|
||||
continue;
|
||||
}
|
||||
done[i] = 1, n_left--;
|
||||
if (i_shdrp->sh_type == SHT_PROGBITS)
|
||||
file_size = i_shdrp->sh_offset + i_shdrp->sh_size - seg->start_pos;
|
||||
mem_size = i_shdrp->sh_addr + i_shdrp->sh_size - seg->low;
|
||||
high = i_shdrp->sh_addr + i_shdrp->sh_size;
|
||||
i = 0;
|
||||
}
|
||||
seg->file_size = file_size;
|
||||
seg->mem_size = mem_size;
|
||||
}
|
||||
/* Now do something with the list of segments we've built up. */
|
||||
{
|
||||
bfd_vma maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
|
||||
struct seg_info *s;
|
||||
int n_segs = 0;
|
||||
int sz;
|
||||
|
||||
for (s = seg; s; s = s->next)
|
||||
{
|
||||
n_segs++;
|
||||
}
|
||||
i_ehdrp->e_phentsize = sizeof (Elf_External_Phdr);
|
||||
sz = sizeof (Elf_External_Phdr) * n_segs;
|
||||
if (i_ehdrp->e_ehsize + sz <= lowest_offset)
|
||||
i_ehdrp->e_phoff = i_ehdrp->e_ehsize;
|
||||
else
|
||||
{
|
||||
i_ehdrp->e_phoff = elf_tdata (abfd)->next_file_pos;
|
||||
elf_tdata (abfd)->next_file_pos += sz;
|
||||
}
|
||||
phdr = bfd_alloc (abfd, n_segs * sizeof (Elf_Internal_Phdr));
|
||||
elf_tdata (abfd)->phdr = phdr;
|
||||
while (seg)
|
||||
{
|
||||
phdr->p_type = PT_LOAD; /* only type we really support so far */
|
||||
phdr->p_offset = seg->start_pos;
|
||||
phdr->p_vaddr = seg->low;
|
||||
phdr->p_paddr = 0;
|
||||
phdr->p_filesz = seg->file_size;
|
||||
phdr->p_memsz = seg->mem_size;
|
||||
phdr->p_flags = PF_R;
|
||||
phdr->p_align = maxpagesize; /* ? */
|
||||
if (seg->sh_flags & SHF_WRITE)
|
||||
phdr->p_flags |= PF_W;
|
||||
if (seg->sh_flags & SHF_EXECINSTR)
|
||||
phdr->p_flags |= PF_X;
|
||||
phdr++;
|
||||
seg = seg->next;
|
||||
}
|
||||
i_ehdrp->e_phnum = n_segs;
|
||||
}
|
||||
elf_write_phdrs (abfd, i_ehdrp, elf_tdata (abfd)->phdr, i_ehdrp->e_phnum);
|
||||
}
|
||||
|
||||
static void
|
||||
assign_file_positions_except_relocs (abfd)
|
||||
bfd *abfd;
|
||||
|
@ -1795,20 +1980,27 @@ assign_file_positions_except_relocs (abfd)
|
|||
a given section, we don't figure them in here. We'll put them at the
|
||||
end of the file, at positions computed during bfd_close.
|
||||
|
||||
The order, for now: <ehdr> <shdr> <sec1> <sec2> <sec3> ... <rel1> ... */
|
||||
The order, for now: <ehdr> <shdr> <sec1> <sec2> <sec3> ... <rel1> ...
|
||||
or: <ehdr> <phdr> <sec1> <sec2> ... <shdr> <rel1> ... */
|
||||
|
||||
file_ptr off;
|
||||
int i;
|
||||
Elf_Internal_Shdr **i_shdrpp = elf_elfsections (abfd);
|
||||
Elf_Internal_Shdr *i_shdrp;
|
||||
Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
|
||||
int exec_p = (abfd->flags & EXEC_P) != 0;
|
||||
|
||||
/* Everything starts after the ELF file header. */
|
||||
off = i_ehdrp->e_ehsize;
|
||||
i_ehdrp->e_shoff = off;
|
||||
off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
|
||||
off = assign_file_position_for_section (&elf_tdata(abfd)->shstrtab_hdr, off);
|
||||
off = assign_file_position_for_section (&elf_tdata(abfd)->symtab_hdr, off);
|
||||
off = assign_file_position_for_section (&elf_tdata(abfd)->strtab_hdr, off);
|
||||
|
||||
if (!exec_p)
|
||||
{
|
||||
/* Section headers. */
|
||||
i_ehdrp->e_shoff = off;
|
||||
off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
|
||||
|
||||
off = assign_file_positions_for_symtab_and_strtabs (abfd, off);
|
||||
}
|
||||
for (i = 0; i < i_ehdrp->e_shnum; i++)
|
||||
{
|
||||
i_shdrp = i_shdrpp[i];
|
||||
|
@ -1817,7 +2009,70 @@ assign_file_positions_except_relocs (abfd)
|
|||
i_shdrp->sh_offset = -1;
|
||||
continue;
|
||||
}
|
||||
if (exec_p)
|
||||
{
|
||||
bfd_vma maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
|
||||
if (maxpagesize == 0)
|
||||
maxpagesize = 1; /* make the arithmetic work */
|
||||
/* This isn't necessarily going to give the best packing, if the
|
||||
segments require padding between them, but since that isn't
|
||||
usually the case, this'll do. */
|
||||
if ((i_shdrp->sh_flags & SHF_ALLOC) == 0)
|
||||
{
|
||||
i_shdrp->sh_offset = -1;
|
||||
continue;
|
||||
}
|
||||
/* Blindly assume that the segments are ordered optimally. With
|
||||
the default LD script, they will be. */
|
||||
{
|
||||
/* need big unsigned type */
|
||||
bfd_vma addtl_off;
|
||||
addtl_off = i_shdrp->sh_addr - off;
|
||||
addtl_off = addtl_off % maxpagesize;
|
||||
if (addtl_off)
|
||||
{
|
||||
off += addtl_off;
|
||||
}
|
||||
}
|
||||
if (i_shdrp->sh_type == SHT_NOBITS)
|
||||
{
|
||||
file_ptr off2;
|
||||
i_shdrp->sh_offset = off;
|
||||
if (off % maxpagesize != 0)
|
||||
off2 = maxpagesize - (off % maxpagesize);
|
||||
if (off2 > i_shdrp->sh_size)
|
||||
off2 = i_shdrp->sh_size;
|
||||
off += off2;
|
||||
}
|
||||
}
|
||||
off = assign_file_position_for_section (i_shdrp, off);
|
||||
if (exec_p
|
||||
&& get_elf_backend_data(abfd)->maxpagesize > 1
|
||||
&& i_shdrp->sh_type == SHT_PROGBITS
|
||||
&& (i_shdrp->sh_flags & SHF_ALLOC)
|
||||
&& (i_shdrp->sh_offset - i_shdrp->sh_addr) % get_elf_backend_data(abfd)->maxpagesize != 0)
|
||||
abort ();
|
||||
}
|
||||
if (exec_p)
|
||||
{
|
||||
elf_tdata (abfd)->next_file_pos = off;
|
||||
map_program_segments (abfd);
|
||||
off = elf_tdata (abfd)->next_file_pos;
|
||||
|
||||
/* Section headers. */
|
||||
i_ehdrp->e_shoff = off;
|
||||
off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
|
||||
|
||||
off = assign_file_positions_for_symtab_and_strtabs (abfd, off);
|
||||
|
||||
for (i = 0; i < i_ehdrp->e_shnum; i++)
|
||||
{
|
||||
i_shdrp = i_shdrpp[i];
|
||||
if (i_shdrp->sh_offset + 1 == 0
|
||||
&& i_shdrp->sh_type != SHT_REL
|
||||
&& i_shdrp->sh_type != SHT_RELA)
|
||||
off = assign_file_position_for_section (i_shdrp, off);
|
||||
}
|
||||
}
|
||||
elf_tdata (abfd)->next_file_pos = off;
|
||||
}
|
||||
|
@ -1906,8 +2161,7 @@ prep_headers (abfd)
|
|||
/* if we're building an executable, we'll need a program header table */
|
||||
if (abfd->flags & EXEC_P)
|
||||
{
|
||||
abort ();
|
||||
|
||||
/* it all happens later */
|
||||
#if 0
|
||||
i_ehdrp->e_phentsize = sizeof (Elf_External_Phdr);
|
||||
|
||||
|
@ -2117,30 +2371,6 @@ write_shdrs_and_ehdr (abfd)
|
|||
bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
|
||||
bfd_write ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd);
|
||||
|
||||
/* If we're building an executable, fixup the program header table
|
||||
offsets.
|
||||
|
||||
@@ For now, assume that the entries are in a fixed order: text,
|
||||
data, bss. FIXME */
|
||||
|
||||
if (abfd->flags & EXEC_P)
|
||||
{
|
||||
static char *CONST section_name[] =
|
||||
{".text", ".data", ".bss"};
|
||||
|
||||
for (count = 0; count < 3; count++)
|
||||
{
|
||||
asection *asect = bfd_get_section_by_name (abfd,
|
||||
section_name[count]);
|
||||
int sh_idx = elf_section_from_bfd_section (abfd, asect);
|
||||
|
||||
i_phdrp[count].p_offset = i_shdrp[sh_idx]->sh_offset;
|
||||
}
|
||||
|
||||
/* write out the program header table entries */
|
||||
elf_write_phdrs (abfd, i_ehdrp, i_phdrp, i_ehdrp->e_phnum);
|
||||
}
|
||||
|
||||
/* at this point we've concocted all the ELF sections... */
|
||||
x_shdrp = (Elf_External_Shdr *)
|
||||
bfd_alloc (abfd, sizeof (*x_shdrp) * (i_ehdrp->e_shnum));
|
||||
|
@ -2192,11 +2422,8 @@ DEFUN (NAME(bfd_elf,write_object_contents), (abfd), bfd * abfd)
|
|||
|
||||
if (abfd->output_has_begun == false)
|
||||
{
|
||||
malloc (0);
|
||||
prep_headers (abfd);
|
||||
malloc(0);
|
||||
elf_compute_section_file_positions (abfd);
|
||||
malloc(0);
|
||||
abfd->output_has_begun = true;
|
||||
}
|
||||
|
||||
|
@ -2204,7 +2431,6 @@ malloc(0);
|
|||
i_ehdrp = elf_elfheader (abfd);
|
||||
|
||||
bfd_map_over_sections (abfd, write_relocs, (PTR) 0);
|
||||
malloc(0);
|
||||
assign_file_positions_for_relocs (abfd);
|
||||
|
||||
/* After writing the headers, we need to write the sections too... */
|
||||
|
@ -2513,6 +2739,7 @@ DEFUN (elf_slurp_symbol_table, (abfd, symptrs),
|
|||
sym->symbol.flags |= BSF_FUNCTION;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Is this a definition of $global$? If so, keep it because it will be
|
||||
needd if any relocations are performed. */
|
||||
if (!strcmp (sym->symbol.name, "$global$")
|
||||
|
|
Loading…
Reference in a new issue