Hi,
I've been watching the project, and trying out elftoolchain's linker,
though I'm running it on Linux. It looks like it mostly works.
I've gotten it to link a working musl libc. That involved changing it
to link as a dynamic executable despite not linking to any shared
libraries, as well as some small fixes. The one thing I'm unsure about
here is the change I made to ld_reloc.c. It makes a working musl libc,
but I got to that point by looking at the symbols musl was segfaulting
on when loading itself and the output differences in readelf between
musl linked with binutils and elftoolchain.
I've also gotten it to link a working
llvm/clang/lld/libc++/libc++abi/libunwind as well. That was mostly
dealing with some peculiarities of musl (empty libm.a, etc), falling
back to parsing a file as a linker script when the it isn't detected
as a library (for linking with libc++, because libc++.so is a linker
script), and dealing with archive files being referenced multiple
times on the command line, resulting in duplicate symbols. I also had
to disable llvm's version scripts passed to the linker when compiling
it, which were causing ld to segfault. I haven't looked into that much
yet.
Patches attached.
~ BwackNinja
diff -ur elftoolchain-0.7.1/ld/ld_dynamic.c elftoolchain-0.7.1.musl/ld/ld_dynamic.c
--- elftoolchain-0.7.1/ld/ld_dynamic.c Sun Feb 7 11:39:17 2016
+++ elftoolchain-0.7.1.musl/ld/ld_dynamic.c Wed May 11 03:08:11 2016
@@ -57,9 +57,6 @@
/* Check how many DSOs is needed for output object. */
_check_dso_needed(ld, lo);
- /* Link statically if we don't use DSOs? */
- if (lo->lo_dso_needed == 0)
- return;
ld->ld_dynamic_link = 1;
@@ -99,7 +99,7 @@
lo = ld->ld_output;
assert(lo != NULL);
- if (lo->lo_dso_needed == 0)
+ if (ld->ld_dynamic_link == 0)
return;
/* Finalize .dynamic section */
@@ -436,10 +436,12 @@
end64 = (Elf64_Dyn *) (uintptr_t) (odb->odb_buf + odb->odb_size);
/* DT_NEEDED. */
- for (p = (int *) (uintptr_t) utarray_front(lo->lo_dso_nameindex);
- p != NULL;
- p = (int *) (uintptr_t) utarray_next(lo->lo_dso_nameindex, p))
- DT_ENTRY_VAL(DT_NEEDED, *p);
+ if (lo->lo_dso_needed) {
+ for (p = (int *) (uintptr_t) utarray_front(lo->lo_dso_nameindex);
+ p != NULL;
+ p = (int *) (uintptr_t) utarray_next(lo->lo_dso_nameindex, p))
+ DT_ENTRY_VAL(DT_NEEDED, *p);
+ }
/* DT_SONAME. */
if (ld->ld_soname != NULL)
diff -ur elftoolchain-0.7.1/ld/ld_layout.c elftoolchain-0.7.1.musl/ld/ld_layout.c
--- elftoolchain-0.7.1/ld/ld_layout.c Fri Dec 11 21:39:06 2015
+++ elftoolchain-0.7.1.musl/ld/ld_layout.c Mon May 9 02:04:08 2016
@@ -388,7 +388,7 @@
* PT_PHDR and PT_DYNAMIC for dynamic linking. But
* do not create PT_PHDR for shared libraries.
*/
- if (lo->lo_dso_needed > 0) {
+ if (ld->ld_dynamic_link) {
num_phdrs++;
if (!ld->ld_dso)
num_phdrs++;
diff -ur elftoolchain-0.7.1/ld/ld_output.c elftoolchain-0.7.1.musl/ld/ld_output.c
--- elftoolchain-0.7.1/ld/ld_output.c Fri Dec 11 21:39:23 2015
+++ elftoolchain-0.7.1.musl/ld/ld_output.c Wed May 11 03:53:39 2016
@@ -715,7 +715,7 @@
addr = os->os_addr - os->os_off;
/* Create PT_PHDR segment for dynamically linked output object */
- if (lo->lo_dso_needed > 0 && !ld->ld_dso) {
+ if (ld->ld_dynamic_link && !ld->ld_dso) {
i++;
off = gelf_fsize(lo->lo_elf, ELF_T_EHDR, 1, EV_CURRENT);
phdr_addr = addr + off;
diff -ur elftoolchain-0.7.1/ld/ld_ehframe.c elftoolchain-0.7.1.musl/ld/ld_ehframe.c
--- elftoolchain-0.7.1/ld/ld_ehframe.c Tue Sep 10 02:46:06 2013
+++ elftoolchain-0.7.1.musl/ld/ld_ehframe.c Sat May 7 16:32:34 2016
@@ -421,7 +421,8 @@
* .eh_frame section content should already be preloaded
* in is->is_ibuf.
*/
- assert(is->is_ibuf != NULL && is->is_size > 0);
+ if (is->is_ibuf == NULL || is->is_size == 0)
+ return;
shrink = 0;
p = is->is_ibuf;
@@ -491,8 +492,8 @@
* used to parse assoicated FDE's later.
*/
cie_version = *p++;
- if (cie_version != 1) {
- ld_warn(ld, "unsupported CIE version");
+ if (cie_version != 1 && cie_version != 3) {
+ ld_warn(ld, "unsupported CIE version %d", cie_version);
goto ignore_cie;
}
augment = p;
@@ -513,7 +514,10 @@
(void) _decode_sleb128(&p);
/* Skip RA. */
- p++;
+ if (cie_version == 1)
+ p++;
+ else
+ (void) _decode_uleb128(&p);
/* Parse augmentation data. */
auglen = _decode_uleb128(&p);
diff -ur elftoolchain-0.7.1/ld/ld_reloc.c elftoolchain-0.7.1.musl/ld/ld_reloc.c
--- elftoolchain-0.7.1/ld/ld_reloc.c Sun Aug 25 16:34:57 2013
+++ elftoolchain-0.7.1.musl/ld/ld_reloc.c Sun Jun 12 22:19:39 2016
@@ -778,9 +778,9 @@
* to *_RELATIVE relocation if the symbol is undefined, or if the
* symbol can be overridden.
*/
- if (ld->ld_dso && (lsb->lsb_shndx == SHN_UNDEF ||
- ld_symbols_overridden(ld, lsb)))
+ if ((ld->ld_dso && (lsb->lsb_shndx == SHN_UNDEF ||
+ ld_symbols_overridden(ld, lsb))) && lsb->lsb_type == STT_FUNC)
return (0);
/* Otherwise it's ok to use *_RELATIVE. */
return (1);
diff -u -r a/ld/ld_file.c b/ld/ld_file.c
--- a/ld/ld_file.c 2014-05-30 18:18:28.012647000 -0400
+++ b/ld/ld_file.c 2014-05-30 18:16:59.924643125 -0400
@@ -114,6 +114,11 @@
if (lf->lf_type == LFT_BINARY)
return;
+ /* skip empty archive */
+ if (lf->lf_size == 8) {
+ return;
+ }
+
if ((lf->lf_elf = elf_memory(lf->lf_mmap, lf->lf_size)) == NULL)
ld_fatal(ld, "%s: elf_memory failed: %s", lf->lf_name,
elf_errmsg(-1));
@@ -131,8 +136,10 @@
}
assert(k != ELF_K_AR);
- if (k == ELF_K_NONE)
- ld_fatal(ld, "%s: File format not recognized", lf->lf_name);
+ if (k == ELF_K_NONE) {
+ ld_script_parse(lf->lf_name);
+ return;
+ }
if (gelf_getehdr(lf->lf_elf, &ehdr) == NULL)
ld_fatal(ld, "%s: gelf_getehdr failed: %s", lf->lf_name,
diff -u -r a/ld/ld_symbols.c b/ld/ld_symbols.c
--- a/ld/ld_symbols.c 2014-05-30 18:18:28.005646999 -0400
+++ b/ld/ld_symbols.c 2014-05-30 18:16:59.923643125 -0400
@@ -230,7 +230,7 @@
ld_symbols_resolve(struct ld *ld)
{
struct ld_state *ls;
- struct ld_file *lf;
+ struct ld_file *lf, *lf2;
struct ld_symbol *lsb, *_lsb;
if (TAILQ_EMPTY(&ld->ld_lflist)) {
@@ -256,6 +256,18 @@
}
ls->ls_group_level = lf->lf_group_level;
+ /* skip file if it exists later in the list */
+ lf2 = TAILQ_NEXT(lf, lf_next);
+ while (lf2 != NULL) {
+ if (!strcmp(lf2->lf_name, lf->lf_name))
+ break;
+ lf2 = TAILQ_NEXT(lf2, lf_next);
+ }
+ if (lf2 != NULL) {
+ lf = TAILQ_NEXT(lf, lf_next);
+ continue;
+ }
+
/* Load symbols. */
ld_file_load(ld, lf);
if (ls->ls_arch_conflict) {
@@ -522,7 +534,9 @@
_lsb.lsb_other = 0;
_write_to_dynsym_table(ld, &_lsb);
- assert(ld->ld_dyn_symbols != NULL);
+ if (ld->ld_dyn_symbols == NULL) {
+ return;
+ }
STAILQ_FOREACH(lsb, ld->ld_dyn_symbols, lsb_dyn) {
if (lsb->lsb_import) {
@@ -1085,7 +1099,9 @@
int extracted, i;
assert(lf != NULL && lf->lf_type == LFT_ARCHIVE);
- assert(lf->lf_ar != NULL);
+ if (lf->lf_ar == NULL) {
+ return;
+ }
ls = &ld->ld_state;
la = lf->lf_ar;
@@ -1196,6 +1212,8 @@
static void
_load_symbols(struct ld *ld, struct ld_file *lf)
{
+ if (elf_kind(lf->lf_elf) == ELF_K_NONE)
+ return;
if (lf->lf_type == LFT_ARCHIVE)
_load_archive_symbols(ld, lf);
diff -u -r a/ld/ld_reloc.c b/ld/ld_reloc.c
--- a/ld/ld_reloc.c 2016-12-11 11:23:08.598552901 -0500
+++ b/ld/ld_reloc.c 2016-12-11 10:58:57.605489073 -0500
@@ -613,6 +613,13 @@
ld->ld_arch->is_relative_reloc(b->lre_type))
return (1);
+ /*
+ * If we're discarding either, the order doesn't matter
+ */
+ if (a->lre_tis->is_discard || b->lre_tis->is_discard) {
+ return (0);
+ }
+
if (ld->ld_arch->is_relative_reloc(a->lre_type) &&
ld->ld_arch->is_relative_reloc(b->lre_type)) {
if (_reloc_addr(a) < _reloc_addr(b))
------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today.http://sdm.link/xeonphi
_______________________________________________
Elftoolchain-developers mailing list
Elftoolchain-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/elftoolchain-developers