diff options
| author | Ulrich Drepper <[email protected]> | 2006-06-12 22:40:23 +0000 |
|---|---|---|
| committer | Ulrich Drepper <[email protected]> | 2006-06-12 22:40:23 +0000 |
| commit | 6ca4600fb59d1e1ae3dfb872b184ac91f10c473f (patch) | |
| tree | df850603e6b4df8787b23a46321c13f60e53bac1 /src | |
| parent | cbb51e5253e05d98af8bdaf2217fed00b2e489b9 (diff) | |
Don't create INTERP and PHDR program header entry if a DSO is created without
a specific interpreter.
Ignore duplicate COMDAT group sections.
elflint should not complain about anything about *_NONE relocations.
Add support to libebl to determine whether given relocation is *_NONE
relocation.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 22 | ||||
| -rw-r--r-- | src/elflint.c | 4 | ||||
| -rw-r--r-- | src/i386_ld.c | 29 | ||||
| -rw-r--r-- | src/ld.h | 2 | ||||
| -rw-r--r-- | src/ldgeneric.c | 156 | ||||
| -rw-r--r-- | src/ldscript.y | 3 |
6 files changed, 156 insertions, 60 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 74ea2bfa..c7c113e4 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,25 @@ +2006-06-12 Ulrich Drepper <[email protected]> + + * ldgeneric.c (ld_generic_generate_sections): Don't create .interp + section if creating a DSO and no interpreter is given. + (ld_generic_create_outfile): Don't store reference to symbols in + discarded COMDAT groups. Don't create PHDR and INTERP program header + for DSO if no interpreter is specified. + * ldscript.y (content): If a DSO is created don't set default + interpreter from linker script. + + * i386_ld.c (elf_i386_count_relocations): Do not add relocations + for symbols in discarded COMDAT groups. + (elf_i386_create_relocations): Likewise. + * ld.h (struct scninfo): Add unused_comdat. + * ldgeneric.c (add_section): Also check group signature when + matching COMDAT sections. + (add_relocatable_file): Ignore symbols in COMDAT group which are + discarded. + + * elflint.c (check_one_reloc): For *_NONE relocs only check type + and symbol reference. + 2006-06-11 Ulrich Drepper <[email protected]> * elflint.c (check_dynamic): Fix checking value of tags which are diff --git a/src/elflint.c b/src/elflint.c index b1eb5d3d..cd335fe6 100644 --- a/src/elflint.c +++ b/src/elflint.c @@ -1170,6 +1170,10 @@ section [%2d] '%s': relocation %zu: relocation type invalid for the file type\n" section [%2d] '%s': relocation %zu: invalid symbol index\n"), idx, section_name (ebl, idx), cnt); + /* No more tests if this is a no-op relocation. */ + if (ebl_none_reloc_p (ebl, GELF_R_TYPE (r_info))) + return; + if (ebl_gotpc_reloc_check (ebl, GELF_R_TYPE (r_info))) { const char *name; diff --git a/src/i386_ld.c b/src/i386_ld.c index d1a213d6..a0c77dbe 100644 --- a/src/i386_ld.c +++ b/src/i386_ld.c @@ -525,6 +525,11 @@ elf_i386_count_relocations (struct ld_state *statep, struct scninfo *scninfo) { Elf32_Word r_sym = XELF_R_SYM (rel->r_info); + /* Symbols in COMDAT group sections which are discarded do + not have to be relocated. */ + if (unlikely (scninfo->fileinfo->symref[r_sym] == NULL)) + continue; + switch (XELF_R_TYPE (rel->r_info)) { case R_386_GOT32: @@ -717,16 +722,24 @@ elf_i386_create_relocations (struct ld_state *statep, section in the output file and the addend. */ value = scninfo[sym->st_shndx].offset + sym->st_value; } - else if (symref[idx]->in_dso) + else { - /* MERGE.VALUE contains the PLT index. We have to add 1 since - there is this one special PLT entry at the beginning. */ - assert (symref[idx]->merge.value != 0 - || symref[idx]->type != STT_FUNC); - value = pltaddr + symref[idx]->merge.value * PLT_ENTRY_SIZE; + if (symref[idx] == NULL) + /* Symbol in ignored COMDAT group section. */ + continue; + + if (symref[idx]->in_dso) + { + /* MERGE.VALUE contains the PLT index. We have to + add 1 since there is this one special PLT entry + at the beginning. */ + assert (symref[idx]->merge.value != 0 + || symref[idx]->type != STT_FUNC); + value = pltaddr + symref[idx]->merge.value * PLT_ENTRY_SIZE; + } + else + value = symref[idx]->merge.value; } - else - value = symref[idx]->merge.value; /* Address of the relocated memory in the data buffer. */ void *relloc = (char *) data->d_buf + rel->r_offset; @@ -174,6 +174,8 @@ struct usedfiles Elf32_Word allsectionsidx; /* True if the section is used. */ bool used; + /* True if section is an unused COMDAT section. */ + bool unused_comdat; /* Section group number. This is the index of the SHT_GROUP section. */ Elf32_Word grpid; /* Pointer back to the containing file information structure. */ diff --git a/src/ldgeneric.c b/src/ldgeneric.c index c089e0ba..22fac228 100644 --- a/src/ldgeneric.c +++ b/src/ldgeneric.c @@ -991,7 +991,36 @@ add_section (struct usedfiles *fileinfo, struct scninfo *scninfo) } /* XXX Possibly unaligned memory access. */ - is_comdat = ((Elf32_Word *) grpscndata->d_buf)[0] & GRP_COMDAT; + if ((((Elf32_Word *) grpscndata->d_buf)[0] & GRP_COMDAT) != 0) + { + /* We have to compare the group signatures. There might + be sections with the same name but belonging to + groups with different signatures. This means we have + to compare the new group signature with all those + already collected. There might also be some + non-group sections in the mix. */ + struct scninfo *runp = queued->last; + do + { + if (SCNINFO_SHDR (runp->shdr).sh_flags & SHF_GROUP) + { + struct scninfo *grpscn2 + = find_section_group (runp->fileinfo, + elf_ndxscn (runp->scn), + &grpscndata); + + if (strcmp (grpscn->symbols->name, + grpscn2->symbols->name) == 0) + { + scninfo->unused_comdat = is_comdat = true; + break; + } + } + + runp = runp->next; + } + while (runp != queued->last); + } } if (!is_comdat) @@ -1378,6 +1407,11 @@ add_relocatable_file (struct usedfiles *fileinfo, GElf_Word secttype) if (unlikely (shndx == SHN_ABS) && secttype == SHT_DYNSYM) continue; + if ((shndx < SHN_LORESERVE || shndx > SHN_HIRESERVE) + && fileinfo->scninfo[shndx].unused_comdat) + /* The symbol is not used. */ + continue; + /* If the DSO uses symbols determine whether this is the default version. Otherwise we'll ignore the symbol. */ if (versymdata != NULL) @@ -2302,8 +2336,9 @@ ld_generic_generate_sections (struct ld_state *statep) bool need_version = false; /* First the .interp section. */ - new_generated_scn (scn_dot_interp, ".interp", SHT_PROGBITS, SHF_ALLOC, - 0, 1); + if (ld_state.interp != NULL || ld_state.file_type != dso_file_type) + new_generated_scn (scn_dot_interp, ".interp", SHT_PROGBITS, SHF_ALLOC, + 0, 1); /* Now the .dynamic section. */ new_generated_scn (scn_dot_dynamic, ".dynamic", SHT_DYNAMIC, @@ -4739,23 +4774,24 @@ section index too large in dynamic symbol table")); Find the symbol if this has not happened yet. We do not need the information for local symbols. */ if (defp == NULL && cnt >= file->nlocalsymbols) - { - defp = file->symref[cnt]; - assert (defp != NULL); - } + defp = file->symref[cnt]; - /* Store the reference to the symbol record. The - sorting code will have to keep this array in the - correct order, too. */ - ndxtosym[nsym] = defp; - - /* One more entry finished. */ - if (cnt >= file->nlocalsymbols) + /* Ignore symbols in discarded COMDAT group sections. */ + if (defp != NULL) { - assert (file->symref[cnt]->outsymidx == 0); - file->symref[cnt]->outsymidx = nsym; + /* Store the reference to the symbol record. The + sorting code will have to keep this array in the + correct order, too. */ + ndxtosym[nsym] = defp; + + /* One more entry finished. */ + if (cnt >= file->nlocalsymbols) + { + assert (file->symref[cnt]->outsymidx == 0); + file->symref[cnt]->outsymidx = nsym; + } + file->symindirect[cnt] = nsym++; } - file->symindirect[cnt] = nsym++; } } while ((file = file->next) != ld_state.relfiles->next); @@ -5624,10 +5660,16 @@ cannot create hash table section for output file: %s"), /* Add the number of SHT_NOTE sections. We counted them earlier. */ nphdr += ld_state.nnotesections; - /* If we create a DSO or the file is linked against DSOs we have three - more entries: INTERP, PHDR, DYNAMIC. */ + /* If we create a DSO or the file is linked against DSOs we have + at least one more entry: DYNAMIC. If an interpreter is + specified we add PHDR and INTERP, too. */ if (dynamically_linked_p ()) - nphdr += 3; + { + ++nphdr; + + if (ld_state.interp != NULL || ld_state.file_type != dso_file_type) + nphdr += 2; + } /* Create the program header structure. */ if (xelf_newphdr (ld_state.outelf, nphdr) == 0) @@ -5655,7 +5697,14 @@ cannot create hash table section for output file: %s"), addr = shdr->sh_offset; /* The index of the first loadable segment. */ - nphdr = 1 + (dynamically_linked_p () == true) * 2; + nphdr = 0; + if (dynamically_linked_p ()) + { + ++nphdr; + if (ld_state.interp != NULL + || ld_state.file_type != dso_file_type) + nphdr += 2; + } segment = ld_state.output_segments; while (segment != NULL) @@ -5813,18 +5862,6 @@ internal error: nobits section follows nobits section")); xelf_getehdr (ld_state.outelf, ehdr); assert (ehdr != NULL); - xelf_getphdr_ptr (ld_state.outelf, 0, phdr); - phdr->p_type = PT_PHDR; - phdr->p_offset = ehdr->e_phoff; - phdr->p_vaddr = ld_state.output_segments->addr + phdr->p_offset; - phdr->p_paddr = phdr->p_vaddr; - phdr->p_filesz = ehdr->e_phnum * ehdr->e_phentsize; - phdr->p_memsz = phdr->p_filesz; - phdr->p_flags = 0; /* No need to set PF_R or so. */ - phdr->p_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1); - (void) xelf_update_phdr (ld_state.outelf, 0, phdr); - - /* Add the stack information. */ xelf_getphdr_ptr (ld_state.outelf, nphdr, phdr); phdr->p_type = PT_GNU_STACK; @@ -5941,24 +5978,41 @@ internal error: nobits section follows nobits section")); { Elf_Scn *outscn; - assert (ld_state.interpscnidx != 0); - xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.interpscnidx), - shdr); - assert (shdr != NULL); + int idx = 0; + if (ld_state.interp != NULL || ld_state.file_type != dso_file_type) + { + assert (ld_state.interpscnidx != 0); + xelf_getshdr (elf_getscn (ld_state.outelf, + ld_state.interpscnidx), shdr); + assert (shdr != NULL); - /* The interpreter string. */ - // XXX Do we need to support files (DSOs) without interpreters? - xelf_getphdr_ptr (ld_state.outelf, 1, phdr); - phdr->p_type = PT_INTERP; - phdr->p_offset = shdr->sh_offset; - phdr->p_vaddr = shdr->sh_addr; - phdr->p_paddr = phdr->p_vaddr; - phdr->p_filesz = shdr->sh_size; - phdr->p_memsz = phdr->p_filesz; - phdr->p_flags = 0; /* No need to set PF_R or so. */ - phdr->p_align = 1; /* It's a string. */ + xelf_getphdr_ptr (ld_state.outelf, idx, phdr); + phdr->p_type = PT_PHDR; + phdr->p_offset = ehdr->e_phoff; + phdr->p_vaddr = ld_state.output_segments->addr + phdr->p_offset; + phdr->p_paddr = phdr->p_vaddr; + phdr->p_filesz = ehdr->e_phnum * ehdr->e_phentsize; + phdr->p_memsz = phdr->p_filesz; + phdr->p_flags = 0; /* No need to set PF_R or so. */ + phdr->p_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1); + + (void) xelf_update_phdr (ld_state.outelf, idx, phdr); + ++idx; + + /* The interpreter string. */ + xelf_getphdr_ptr (ld_state.outelf, idx, phdr); + phdr->p_type = PT_INTERP; + phdr->p_offset = shdr->sh_offset; + phdr->p_vaddr = shdr->sh_addr; + phdr->p_paddr = phdr->p_vaddr; + phdr->p_filesz = shdr->sh_size; + phdr->p_memsz = phdr->p_filesz; + phdr->p_flags = 0; /* No need to set PF_R or so. */ + phdr->p_align = 1; /* It's a string. */ - (void) xelf_update_phdr (ld_state.outelf, 1, phdr); + (void) xelf_update_phdr (ld_state.outelf, idx, phdr); + ++idx; + } /* The pointer to the dynamic section. We this we need to get the information for the dynamic section first. */ @@ -5967,7 +6021,7 @@ internal error: nobits section follows nobits section")); xelf_getshdr (outscn, shdr); assert (shdr != NULL); - xelf_getphdr_ptr (ld_state.outelf, 2, phdr); + xelf_getphdr_ptr (ld_state.outelf, idx, phdr); phdr->p_type = PT_DYNAMIC; phdr->p_offset = shdr->sh_offset; phdr->p_vaddr = shdr->sh_addr; @@ -5977,7 +6031,7 @@ internal error: nobits section follows nobits section")); phdr->p_flags = 0; /* No need to set PF_R or so. */ phdr->p_align = shdr->sh_addralign; - (void) xelf_update_phdr (ld_state.outelf, 2, phdr); + (void) xelf_update_phdr (ld_state.outelf, idx, phdr); /* Fill in the reference to the .dynstr section. */ assert (ld_state.dynstrscnidx != 0); diff --git a/src/ldscript.y b/src/ldscript.y index 764b4157..252f9d4b 100644 --- a/src/ldscript.y +++ b/src/ldscript.y @@ -165,7 +165,8 @@ content: kENTRY '(' kID ')' ';' } | kINTERP '(' filename_id ')' ';' { - if (likely (ld_state.interp == NULL)) + if (likely (ld_state.interp == NULL) + && ld_state.file_type != dso_file_type) ld_state.interp = $3; } | kSEGMENT kMODE '{' outputsections '}' |
