Print this page
10366 ld(1) should support GNU-style linker sets
10367 ld(1) tests should be a real test suite
10368 want an ld(1) regression test for i386 LD tls transition (10267)
@@ -34,10 +34,11 @@
#define ELF_TARGET_AMD64
#include <stdio.h>
#include <string.h>
#include <debug.h>
+#include <alloca.h>
#include "msg.h"
#include "_libld.h"
/*
* AVL tree comparator function:
@@ -690,13 +691,14 @@
*/
if (usdp->sd_flags & FLG_SY_MAPREF)
usdp->sd_flags |= FLG_SY_MAPUSED;
DBG_CALL(Dbg_syms_updated(ofl, usdp, uname));
- } else
+ } else {
ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_RESERVE),
uname, usdp->sd_file->ifl_name);
+ }
} else {
/*
* If the symbol does not exist create it.
*/
if ((sym = libld_calloc(sizeof (Sym), 1)) == NULL)
@@ -883,24 +885,97 @@
ld_eprintf(ofl, ERR_NONE, MSG_INTL(format[type]),
demangle(sdp->sd_name), name1, name2, name3);
}
/*
+ * If an undef symbol exists naming a bound for the output section,
+ * turn it into a defined symbol with the correct value.
+ *
+ * We set an arbitrary 1KB limit on the resulting symbol names.
+ */
+static void
+sym_add_bounds(Ofl_desc *ofl, Os_desc *osp, Word bound)
+{
+ Sym_desc *bsdp;
+ char symn[1024];
+ size_t nsz;
+
+ switch (bound) {
+ case SDAUX_ID_SECBOUND_START:
+ nsz = snprintf(symn, sizeof (symn), "%s%s",
+ MSG_ORIG(MSG_SYM_SECBOUND_START), osp->os_name + 1);
+ if (nsz > sizeof (symn))
+ return;
+ break;
+ case SDAUX_ID_SECBOUND_STOP:
+ nsz = snprintf(symn, sizeof (symn), "%s%s",
+ MSG_ORIG(MSG_SYM_SECBOUND_STOP), osp->os_name + 1);
+ if (nsz > sizeof (symn))
+ return;
+ break;
+ default:
+ assert(0);
+ }
+
+ if ((bsdp = ld_sym_find(symn, SYM_NOHASH, NULL, ofl)) != NULL) {
+ if ((bsdp->sd_shndx != SHN_UNDEF) &&
+ (bsdp->sd_ref == REF_REL_NEED)) {
+ ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_RESERVE),
+ symn, bsdp->sd_file->ifl_name);
+ return;
+ }
+
+ DBG_CALL(Dbg_syms_updated(ofl, bsdp, symn));
+
+ bsdp->sd_aux->sa_symspec = bound;
+ bsdp->sd_aux->sa_boundsec = osp;
+ bsdp->sd_flags |= FLG_SY_SPECSEC;
+ bsdp->sd_ref = REF_REL_NEED;
+ bsdp->sd_sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE);
+ bsdp->sd_sym->st_other = STV_PROTECTED;
+ bsdp->sd_isc = NULL;
+ bsdp->sd_sym->st_size = 0;
+ bsdp->sd_sym->st_value = 0;
+ bsdp->sd_shndx = bsdp->sd_sym->st_shndx = SHN_ABS;
+ }
+}
+
+/*
* At this point all symbol input processing has been completed, therefore
* complete the symbol table entries by generating any necessary internal
* symbols.
*/
uintptr_t
ld_sym_spec(Ofl_desc *ofl)
{
Sym_desc *sdp;
+ Sg_desc *sgp;
+ Aliste idx1;
if (ofl->ofl_flags & FLG_OF_RELOBJ)
return (1);
DBG_CALL(Dbg_syms_spec_title(ofl->ofl_lml));
+ /*
+ * For each section in the output file, look for symbols named for the
+ * __start/__stop patterns. If references exist, flesh the symbols to
+ * be defined.
+ *
+ * the symbols are given values at the same time as the other special
+ * symbols.
+ */
+ for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
+ Os_desc *osp;
+ Aliste idx2;
+
+ for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
+ sym_add_bounds(ofl, osp, SDAUX_ID_SECBOUND_START);
+ sym_add_bounds(ofl, osp, SDAUX_ID_SECBOUND_STOP);
+ }
+ }
+
if (sym_add_spec(MSG_ORIG(MSG_SYM_ETEXT), MSG_ORIG(MSG_SYM_ETEXT_U),
SDAUX_ID_ETEXT, 0, (FLG_SY_DEFAULT | FLG_SY_EXPDEF),
ofl) == S_ERROR)
return (S_ERROR);
if (sym_add_spec(MSG_ORIG(MSG_SYM_EDATA), MSG_ORIG(MSG_SYM_EDATA_U),