int sym7(void) { if(ELF_ST_TYPE(orcSYM->st_info) != STT_FILE) return 0; if(mode & REL) if(rand() % 2) return 0; unsigned char st_info = orcSYM->st_info; Elf_Section st_shndx; if(rand() % 2) do st_info = ELF_ST_INFO(rand() & 0x0f, STT_FILE); while(ELF_ST_BIND(st_info) == STB_LOCAL); if(rand() % 4 < 3){ while((st_shndx = rand() % orcHDR->e_shnum)) if(st_shndx != SHN_ABS) break; } else while((st_shndx = getElf_Section())) if(st_shndx != SHN_ABS) break; orcSYM->st_info = st_info; orcSYM->st_shndx = st_shndx; fprintf(logfp, "(SYM[%d]->st_info = 0x%.2x,", entry, orcSYM->st_info); fprintf(logfp, " st_shndx = 0x%x)", orcSYM->st_shndx); return 1; }
//------------------------------------------------------------------------------ Elf_Word add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size, unsigned char bind, unsigned char type, unsigned char other, Elf_Half shndx ) { return add_symbol( name, value, size, ELF_ST_INFO( bind, type ), other, shndx ); }
//------------------------------------------------------------------------------ Elf_Word add_symbol( string_section_accessor& pStrWriter, const char* str, Elf64_Addr value, Elf_Xword size, unsigned char bind, unsigned char type, unsigned char other, Elf_Half shndx ) { return add_symbol( pStrWriter, str, value, size, ELF_ST_INFO( bind, type ), other, shndx ); }
int sym14(void) { if(rand() % 4 < 3) return 0; if(mode & REL) if(rand() % 2) return 0; orcSYM->st_info = ELF_ST_INFO(rand() % 2 ? STB_LOOS : STB_HIOS, rand() % 2 ? STT_LOOS : STT_HIOS); fprintf(logfp, "(SYM[%d]->st_info = 0x%.2x)", entry, orcSYM->st_info); return 1; }
int sym6(void) { if(ELF_ST_TYPE(orcSYM->st_info) != STT_SECTION) return 0; if(mode & REL) if(rand() % 2) return 0; unsigned char st_info; do st_info = ELF_ST_INFO(rand() & 0x0f, STT_SECTION); while(ELF_ST_BIND(st_info) == STB_LOCAL); orcSYM->st_info = st_info; fprintf(logfp, "(SYM[%d]->st_info = 0x%.2x)", entry, orcSYM->st_info); return 1; }
int reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, RtldLockState *lockstate) { const Elf_Rel *rel; const Elf_Rel *rellim; Elf_Addr *got = obj->pltgot; const Elf_Sym *sym, *def; const Obj_Entry *defobj; Elf_Word i; #ifdef SUPPORT_OLD_BROKEN_LD int broken; #endif /* The relocation for the dynamic loader has already been done. */ if (obj == obj_rtld) return (0); if ((flags & SYMLOOK_IFUNC) != 0) /* XXX not implemented */ return (0); #ifdef SUPPORT_OLD_BROKEN_LD broken = 0; sym = obj->symtab; for (i = 1; i < 12; i++) if (sym[i].st_info == ELF_ST_INFO(STB_LOCAL, STT_NOTYPE)) broken = 1; dbg("%s: broken=%d", obj->path, broken); #endif i = (got[1] & GOT1_MASK) ? 2 : 1; /* Relocate the local GOT entries */ got += i; dbg("got:%p for %d entries adding %p", got, obj->local_gotno, obj->relocbase); for (; i < obj->local_gotno; i++) { *got += (Elf_Addr)obj->relocbase; got++; } sym = obj->symtab + obj->gotsym; dbg("got:%p for %d entries", got, obj->symtabno); /* Now do the global GOT entries */ for (i = obj->gotsym; i < obj->symtabno; i++) { dbg(" doing got %d sym %p (%s, %lx)", i - obj->gotsym, sym, sym->st_name + obj->strtab, (u_long) *got); #ifdef SUPPORT_OLD_BROKEN_LD if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && broken && sym->st_shndx == SHN_UNDEF) { /* * XXX DANGER WILL ROBINSON! * You might think this is stupid, as it intentionally * defeats lazy binding -- and you'd be right. * Unfortunately, for lazy binding to work right, we * need to a way to force the GOT slots used for * function pointers to be resolved immediately. This * is supposed to be done automatically by the linker, * by not outputting a PLT slot and setting st_value * to 0 if there are non-PLT references, but older * versions of GNU ld do not do this. */ def = find_symdef(i, obj, &defobj, flags, NULL, lockstate); if (def == NULL) return -1; *got = def->st_value + (Elf_Addr)defobj->relocbase; } else #endif if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && sym->st_value != 0 && sym->st_shndx == SHN_UNDEF) { /* * If there are non-PLT references to the function, * st_value should be 0, forcing us to resolve the * address immediately. * * XXX DANGER WILL ROBINSON! * The linker is not outputting PLT slots for calls to * functions that are defined in the same shared * library. This is a bug, because it can screw up * link ordering rules if the symbol is defined in * more than one module. For now, if there is a * definition, we fail the test above and force a full * symbol lookup. This means that all intra-module * calls are bound immediately. - mycroft, 2003/09/24 */ *got = sym->st_value + (Elf_Addr)obj->relocbase; if ((Elf_Addr)(*got) == (Elf_Addr)obj->relocbase) { dbg("Warning2, i:%d maps to relocbase address:%p", i, obj->relocbase); } } else if (sym->st_info == ELF_ST_INFO(STB_GLOBAL, STT_SECTION)) { /* Symbols with index SHN_ABS are not relocated. */ if (sym->st_shndx != SHN_ABS) { *got = sym->st_value + (Elf_Addr)obj->relocbase; if ((Elf_Addr)(*got) == (Elf_Addr)obj->relocbase) { dbg("Warning3, i:%d maps to relocbase address:%p", i, obj->relocbase); } } } else { /* TODO: add cache here */ def = find_symdef(i, obj, &defobj, flags, NULL, lockstate); if (def == NULL) { dbg("Warning4, can't find symbole %d", i); return -1; } *got = def->st_value + (Elf_Addr)defobj->relocbase; if ((Elf_Addr)(*got) == (Elf_Addr)obj->relocbase) { dbg("Warning4, i:%d maps to relocbase address:%p", i, obj->relocbase); dbg("via first obj symbol %s", obj->strtab + obj->symtab[i].st_name); dbg("found in obj %p:%s", defobj, defobj->path); } } dbg(" --> now %lx", (u_long) *got); ++sym; ++got; } got = obj->pltgot; rellim = (const Elf_Rel *)((caddr_t)obj->rel + obj->relsize); for (rel = obj->rel; rel < rellim; rel++) { Elf_Word r_symndx, r_type; void *where; where = obj->relocbase + rel->r_offset; r_symndx = ELF_R_SYM(rel->r_info); r_type = ELF_R_TYPE(rel->r_info); switch (r_type & 0xff) { case R_TYPE(NONE): break; case R_TYPE(REL32): { /* 32-bit PC-relative reference */ const size_t rlen = ELF_R_NXTTYPE_64_P(r_type) ? sizeof(Elf_Sxword) : sizeof(Elf_Sword); Elf_Sxword old = load_ptr(where, rlen); Elf_Sxword val = old; def = obj->symtab + r_symndx; if (r_symndx >= obj->gotsym) { val += got[obj->local_gotno + r_symndx - obj->gotsym]; dbg("REL32/G(%p) %p --> %p (%s) in %s", where, (void *)old, (void *)val, obj->strtab + def->st_name, obj->path); } else { /* * XXX: ABI DIFFERENCE! * * Old NetBSD binutils would generate shared * libs with section-relative relocations being * already adjusted for the start address of * the section. * * New binutils, OTOH, generate shared libs * with the same relocations being based at * zero, so we need to add in the start address * of the section. * * --rkb, Oct 6, 2001 */ if (def->st_info == ELF_ST_INFO(STB_LOCAL, STT_SECTION) #ifdef SUPPORT_OLD_BROKEN_LD && !broken #endif ) val += (Elf_Addr)def->st_value; val += (Elf_Addr)obj->relocbase; dbg("REL32/L(%p) %p -> %p (%s) in %s", where, (void *)old, (void *)val, obj->strtab + def->st_name, obj->path); } store_ptr(where, val, rlen); break; } #ifdef __mips_n64 case R_TYPE(TLS_DTPMOD64): #else case R_TYPE(TLS_DTPMOD32): #endif { const size_t rlen = sizeof(Elf_Addr); Elf_Addr old = load_ptr(where, rlen); Elf_Addr val = old; def = find_symdef(r_symndx, obj, &defobj, flags, NULL, lockstate); if (def == NULL) return -1; val += (Elf_Addr)defobj->tlsindex; store_ptr(where, val, rlen); dbg("DTPMOD %s in %s %p --> %p in %s", obj->strtab + obj->symtab[r_symndx].st_name, obj->path, (void *)old, (void*)val, defobj->path); break; } #ifdef __mips_n64 case R_TYPE(TLS_DTPREL64): #else case R_TYPE(TLS_DTPREL32): #endif { const size_t rlen = sizeof(Elf_Addr); Elf_Addr old = load_ptr(where, rlen); Elf_Addr val = old; def = find_symdef(r_symndx, obj, &defobj, flags, NULL, lockstate); if (def == NULL) return -1; if (!defobj->tls_done && allocate_tls_offset(obj)) return -1; val += (Elf_Addr)def->st_value - TLS_DTP_OFFSET; store_ptr(where, val, rlen); dbg("DTPREL %s in %s %p --> %p in %s", obj->strtab + obj->symtab[r_symndx].st_name, obj->path, (void*)old, (void *)val, defobj->path); break; } #ifdef __mips_n64 case R_TYPE(TLS_TPREL64): #else case R_TYPE(TLS_TPREL32): #endif { const size_t rlen = sizeof(Elf_Addr); Elf_Addr old = load_ptr(where, rlen); Elf_Addr val = old; def = find_symdef(r_symndx, obj, &defobj, flags, NULL, lockstate); if (def == NULL) return -1; if (!defobj->tls_done && allocate_tls_offset(obj)) return -1; val += (Elf_Addr)(def->st_value + defobj->tlsoffset - TLS_TP_OFFSET - TLS_TCB_SIZE); store_ptr(where, val, rlen); dbg("TPREL %s in %s %p --> %p in %s", obj->strtab + obj->symtab[r_symndx].st_name, obj->path, (void*)old, (void *)val, defobj->path); break; } default: dbg("sym = %lu, type = %lu, offset = %p, " "contents = %p, symbol = %s", (u_long)r_symndx, (u_long)ELF_R_TYPE(rel->r_info), (void *)rel->r_offset, (void *)load_ptr(where, sizeof(Elf_Sword)), obj->strtab + obj->symtab[r_symndx].st_name); _rtld_error("%s: Unsupported relocation type %ld " "in non-PLT relocations", obj->path, (u_long) ELF_R_TYPE(rel->r_info)); return -1; } } return 0; }
/* * Add a size symbol to a segment * * entry: * mf - Mapfile descriptor * sgp - Segment descriptor * eq_tol - Type of assignment: TK_EQUAL, or TK_PLUSEQ * symname - Name of symbol. Must be in stable static storage * that can be retained. * * exit: * On success, the symbol has been added and true is returned. * Otherwise an error is reported and false is returned. */ bool ld_map_seg_size_symbol(Mapfile *mf, Sg_desc *sgp, Token eq_tok, const char *symname) { Elf64_Sym *sym; /* New symbol pointer */ Sym_desc *sdp; /* New symbol node pointer */ Ifl_desc *ifl; /* Dummy input file structure */ avl_index_t where; Ofl_desc *ofl = mf->mf_ofl; /* * We don't allow resetting the list of size symbols, so if the * operator is TK_EQUAL and the list is not empty, issue an error. * * If we want to lift this restriction, we would have to save the * size symbols and enter them from ld_map_post_process(). Doing that * well would require a significant overhead in saved error reporting * state, and interactions with the same symbols created by symbol * directives. As size symbols are of little practical use, and are * maintained primarily for backward compatibility with SysV, we have * decided not to do that, but to create the symbols as the mapfiles * are processed, and to disallow later attempts to remove them. */ if ((eq_tok == TK_EQUAL) && (aplist_nitems(sgp->sg_sizesym) > 0)) { mf_fatal(mf, (MSG_MAP_SEGSIZE), sgp->sg_name); return (false); } /* * Make sure we have a pseudo file descriptor to associate to the * symbol. */ if ((ifl = ld_map_ifl(mf)) == NULL) return (false); /* * Make sure the symbol doesn't already exist. It is possible that the * symbol has been scoped or versioned, in which case it does exist * but we can freely update it here. */ if ((sdp = ld_sym_find(symname, SYM_NOHASH, &where, ofl)) == NULL) { Elf64_Word hval; if ((sym = libld_calloc(sizeof (Elf64_Sym), 1)) == NULL) return (false); sym->st_shndx = SHN_ABS; sym->st_size = 0; sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT); //DBG_CALL(Dbg_map_size_new(ofl->ofl_lml, symname, // sgp->sg_name, mf->mf_lineno)); /* LINTED */ hval = (Elf64_Word)elf_hash(symname); if ((sdp = ld_sym_enter(symname, sym, hval, ifl, ofl, 0, SHN_ABS, (FLG_SY_SPECSEC | FLG_SY_GLOBREF), &where)) == (Sym_desc *)S_ERROR) return (false); sdp->sd_flags &= ~FLG_SY_CLEAN; //DBG_CALL(Dbg_map_symbol(ofl, sdp)); } else { sym = sdp->sd_sym; if (sym->st_shndx == SHN_UNDEF) { sdp->sd_shndx = sym->st_shndx = SHN_ABS; sdp->sd_flags |= FLG_SY_SPECSEC; sym->st_size = 0; sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT); sdp->sd_flags &= ~FLG_SY_MAPREF; //DBG_CALL(Dbg_map_size_old(ofl, sdp, // sgp->sg_name, mf->mf_lineno)); } else { mf_fatal(mf, (MSG_MAP_SYMDEF1), demangle(sdp->sd_name), sdp->sd_file->ifl_name, (MSG_MAP_DIFF_SYMMUL)); return (false); } } /* * Assign the symbol to the segment. */ if (aplist_append(&sgp->sg_sizesym, sdp, AL_CNT_SG_SIZESYM) == NULL) return (false); return (true); }
/* * Enter a mapfile defined symbol into the given version * * entry: * mf - Mapfile descriptor * ms - Information related to symbol being added to version * * exit: * On success, returns true. On failure that requires an immediate * halt, returns false. * * On failure that requires eventual halt, but for which it would * be OK to continue parsing in hopes of flushing out additional * problems, increments mv->mv_errcnt, and returns true. */ bool ld_map_sym_enter(Mapfile *mf, ld_map_ver_t *mv, ld_map_sym_t *ms) { Ofl_desc *ofl = mf->mf_ofl; Elf64_Word hash; avl_index_t where; Elf64_Sym *sym; Sym_desc *sdp; const char *conflict; /* * Add the new symbol. It should be noted that all * symbols added by the mapfile start out with global * scope, thus they will fall through the normal symbol * resolution process. Elf64_Symbols defined as locals will * be reduced in scope after all input file processing. */ /* LINTED */ hash = (Elf64_Word)elf_hash(ms->ms_name); //DBG_CALL(Dbg_map_version(ofl->ofl_lml, mv->mv_name, ms->ms_name, // mv->mv_scope)); /* * Make sure that any parent or external declarations fall back to * references. */ if (ms->ms_sdflags & (FLG_SY_PARENT | FLG_SY_EXTERN)) { /* * Turn it into a reference by setting the section index * to UNDEF. */ ms->ms_shndx = SHN_UNDEF; /* * It is wrong to specify size or value for an external symbol. */ if (ms->ms_value_set || (ms->ms_size != 0)) { mf_fatal0(mf, (MSG_MAP_NOEXVLSZ)); mv->mv_errcnt++; return (true); } } if ((sdp = ld_sym_find(ms->ms_name, hash, &where, ofl)) == NULL) { if ((sym = libld_calloc(sizeof (Elf64_Sym), 1)) == NULL) return (false); sym->st_shndx = (Elf64_Half)ms->ms_shndx; sym->st_value = ms->ms_value; sym->st_size = ms->ms_size; sym->st_info = ELF_ST_INFO(STB_GLOBAL, ms->ms_type); if ((sdp = ld_sym_enter(ms->ms_name, sym, hash, ld_map_ifl(mf), ofl, 0, ms->ms_shndx, ms->ms_sdflags, &where)) == (Sym_desc *)S_ERROR) return (false); sdp->sd_flags &= ~FLG_SY_CLEAN; /* * Identify any references. FLG_SY_MAPREF is * turned off once a relocatable object with * the same symbol is found, thus the existence * of FLG_SY_MAPREF at symbol validation is * used to flag undefined/misspelled entries. */ if (sym->st_shndx == SHN_UNDEF) sdp->sd_flags |= (FLG_SY_MAPREF | FLG_SY_GLOBREF); } else { conflict = NULL; sym = sdp->sd_sym; /* * If this symbol already exists, make sure this * definition doesn't conflict with the former. * Provided it doesn't, multiple definitions * from different mapfiles can augment each * other. */ if (sym->st_value) { if (ms->ms_value && (sym->st_value != ms->ms_value)) conflict = (MSG_MAP_DIFF_SYMVAL); } else { sym->st_value = ms->ms_value; } if (sym->st_size) { if (ms->ms_size && (sym->st_size != ms->ms_size)) conflict = (MSG_MAP_DIFF_SYMSZ); } else { sym->st_size = ms->ms_size; } if (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) { if ((ms->ms_type != STT_NOTYPE) && (ELF_ST_TYPE(sym->st_info) != ms->ms_type)) conflict = (MSG_MAP_DIFF_SYMTYP); } else { sym->st_info = ELF_ST_INFO(STB_GLOBAL, ms->ms_type); } if (sym->st_shndx != SHN_UNDEF) { if ((ms->ms_shndx != SHN_UNDEF) && (sym->st_shndx != ms->ms_shndx)) conflict = (MSG_MAP_DIFF_SYMNDX); } else { sym->st_shndx = sdp->sd_shndx = ms->ms_shndx; } if ((sdp->sd_flags & MSK_SY_GLOBAL) && (sdp->sd_aux->sa_overndx != VER_NDX_GLOBAL) && (mv->mv_vdp->vd_ndx != VER_NDX_GLOBAL) && (sdp->sd_aux->sa_overndx != mv->mv_vdp->vd_ndx)) { conflict = (MSG_MAP_DIFF_SYMVER); } if (conflict) { mf_fatal(mf, (MSG_MAP_SYMDEF1), demangle(ms->ms_name), sdp->sd_file->ifl_name, conflict); mv->mv_errcnt++; return (true); } /* * If this mapfile entry supplies a definition, * indicate that the symbol is now used. */ if (ms->ms_shndx != SHN_UNDEF) sdp->sd_flags |= FLG_SY_MAPUSED; } /* * A symbol declaration that defines a size but no * value is processed as a request to create an * associated backing section. The intent behind this * functionality is to provide OBJT definitions within * filters that are not ABS. ABS symbols don't allow * copy-relocations to be established to filter OBJT * definitions. */ if ((ms->ms_shndx == SHN_ABS) && ms->ms_size && !ms->ms_value_set) { /* Create backing section if not there */ if (sdp->sd_isc == NULL) { Is_desc *isp; if (ms->ms_type == STT_OBJECT) { if ((isp = ld_make_data(ofl, ms->ms_size)) == (Is_desc *)S_ERROR) return (false); } else { if ((isp = ld_make_text(ofl, ms->ms_size)) == (Is_desc *)S_ERROR) return (false); } sdp->sd_isc = isp; isp->is_file = ld_map_ifl(mf); } /* * Now that backing storage has been created, * associate the symbol descriptor. Remove the * symbols special section tag so that it will * be assigned the correct section index as part * of update symbol processing. */ sdp->sd_flags &= ~FLG_SY_SPECSEC; ms->ms_sdflags &= ~FLG_SY_SPECSEC; } /* * Indicate the new symbols scope. Although the * symbols st_other field will eventually be updated as * part of writing out the final symbol, update the * st_other field here to trigger better diagnostics * during symbol validation (for example, undefined * references that are defined symbolic in a mapfile). */ if (mv->mv_scope == FLG_SCOPE_HIDD) { /* * This symbol needs to be reduced to local. */ if (ofl->ofl_flags & FLG_OF_REDLSYM) { sdp->sd_flags |= (FLG_SY_HIDDEN | FLG_SY_ELIM); sdp->sd_sym->st_other = STV_ELIMINATE; } else { sdp->sd_flags |= FLG_SY_HIDDEN; sdp->sd_sym->st_other = STV_HIDDEN; } } else if (mv->mv_scope == FLG_SCOPE_ELIM) { /* * This symbol needs to be eliminated. Note, * the symbol is also tagged as local to trigger * any necessary relocation processing prior * to the symbol being eliminated. */ sdp->sd_flags |= (FLG_SY_HIDDEN | FLG_SY_ELIM); sdp->sd_sym->st_other = STV_ELIMINATE; } else { /* * This symbol is explicitly defined to remain * global. */ sdp->sd_flags |= ms->ms_sdflags; /* * Qualify any global scope. */ if (mv->mv_scope == FLG_SCOPE_SNGL) { sdp->sd_flags |= (FLG_SY_SINGLE | FLG_SY_NDIR); sdp->sd_sym->st_other = STV_SINGLETON; } else if (mv->mv_scope == FLG_SCOPE_PROT) { sdp->sd_flags |= FLG_SY_PROTECT; sdp->sd_sym->st_other = STV_PROTECTED; } else if (mv->mv_scope == FLG_SCOPE_EXPT) { sdp->sd_flags |= FLG_SY_EXPORT; sdp->sd_sym->st_other = STV_EXPORTED; } else sdp->sd_flags |= FLG_SY_DEFAULT; /* * Record the present version index for later * potential versioning. */ if ((sdp->sd_aux->sa_overndx == 0) || (sdp->sd_aux->sa_overndx == VER_NDX_GLOBAL)) sdp->sd_aux->sa_overndx = mv->mv_vdp->vd_ndx; mv->mv_vdp->vd_flags |= FLG_VER_REFER; } conflict = NULL; /* * Carry out some validity checks to ensure incompatible * symbol characteristics have not been defined. * These checks are carried out after symbols are added * or resolved, to catch single instance, and * multi-instance definition inconsistencies. */ if ((sdp->sd_flags & (FLG_SY_HIDDEN | FLG_SY_ELIM)) && ((mv->mv_scope != FLG_SCOPE_HIDD) && (mv->mv_scope != FLG_SCOPE_ELIM))) { conflict = (MSG_MAP_DIFF_SYMLCL); } else if ((sdp->sd_flags & (FLG_SY_SINGLE | FLG_SY_EXPORT)) && ((mv->mv_scope != FLG_SCOPE_DFLT) && (mv->mv_scope != FLG_SCOPE_EXPT) && (mv->mv_scope != FLG_SCOPE_SNGL))) { conflict = (MSG_MAP_DIFF_SYMGLOB); } else if ((sdp->sd_flags & FLG_SY_PROTECT) && ((mv->mv_scope != FLG_SCOPE_DFLT) && (mv->mv_scope != FLG_SCOPE_PROT))) { conflict = (MSG_MAP_DIFF_SYMPROT); } else if ((sdp->sd_flags & FLG_SY_NDIR) && (mv->mv_scope == FLG_SCOPE_PROT)) { conflict = (MSG_MAP_DIFF_PROTNDIR); } else if ((sdp->sd_flags & FLG_SY_DIR) && (mv->mv_scope == FLG_SCOPE_SNGL)) { conflict = (MSG_MAP_DIFF_SNGLDIR); } if (conflict) { /* * Select the conflict message from either a * single instance or multi-instance definition. */ if (sdp->sd_file->ifl_name == mf->mf_name) { mf_fatal(mf, (MSG_MAP_SYMDEF2), demangle(ms->ms_name), conflict); } else { mf_fatal(mf, (MSG_MAP_SYMDEF1), demangle(ms->ms_name), sdp->sd_file->ifl_name, conflict); } mv->mv_errcnt++; return (true); } /* * Indicate that this symbol has been explicitly * contributed from a mapfile. */ sdp->sd_flags |= (FLG_SY_MAPFILE | FLG_SY_EXPDEF); /* * If we've encountered a symbol definition simulate * that an input file has been processed - this allows * things like filters to be created purely from a * mapfile. */ if (ms->ms_type != STT_NOTYPE) ofl->ofl_objscnt++; //DBG_CALL(Dbg_map_symbol(ofl, sdp)); /* * If this symbol has an associated filtee, record the * filtee string and associate the string index with the * symbol. This is used later to associate the syminfo * information with the necessary .dynamic entry. */ if (ms->ms_filtee) { Dfltr_desc * dftp; Sfltr_desc sft; size_t idx, _idx, nitems; /* * Make sure we don't duplicate any filtee * strings, and create a new descriptor if * necessary. */ idx = nitems = alist_nitems(ofl->ofl_dtsfltrs); for (ALIST_TRAVERSE(ofl->ofl_dtsfltrs, _idx, dftp)) { if ((ms->ms_dft_flag != dftp->dft_flag) || (strcmp(dftp->dft_str, ms->ms_filtee))) continue; idx = _idx; break; } if (idx == nitems) { Dfltr_desc dft; dft.dft_str = ms->ms_filtee; dft.dft_flag = ms->ms_dft_flag; dft.dft_ndx = 0; /* * The following append puts the new * item at the offset contained in * idx, because we know idx contains * the index of the next available slot. */ if (alist_append(&ofl->ofl_dtsfltrs, &dft, sizeof (Dfltr_desc), AL_CNT_OFL_DTSFLTRS) == NULL) return (false); } /* * Create a new filter descriptor for this * symbol. */ sft.sft_sdp = sdp; sft.sft_idx = idx; if (alist_append(&ofl->ofl_symfltrs, &sft, sizeof (Sfltr_desc), AL_CNT_OFL_SYMFLTRS) == NULL) return (false); }
flagword *flagsp, asection **secp ATTRIBUTE_UNUSED, bfd_vma *valp ATTRIBUTE_UNUSED) { /* Ideally these "magic" symbols would be exported by libc.so.1 which would be found via a DT_NEEDED tag, and then handled specially by the linker at runtime. Except shared libraries don't even link to libc.so.1 by default... If the symbol is imported from, or will be put in a shared library, give the symbol weak binding to get the desired samantics. This transformation will be undone in elf_i386_vxworks_link_output_symbol_hook. */ if ((bfd_link_pic (info) || abfd->flags & DYNAMIC) && elf_vxworks_gott_symbol_p (abfd, *namep)) { sym->st_info = ELF_ST_INFO (STB_WEAK, ELF_ST_TYPE (sym->st_info)); *flagsp |= BSF_WEAK; } return TRUE; } /* Perform VxWorks-specific handling of the create_dynamic_sections hook. When creating an executable, set *SRELPLT2_OUT to the .rel(a).plt.unloaded section. */ bfd_boolean elf_vxworks_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info, asection **srelplt2_out) { struct elf_link_hash_table *htab;
uintptr_t ld_vers_check_defs(Ofl_desc *ofl) { size_t idx1; Ver_desc *vdp; uintptr_t is_cyclic = 0; //DBG_CALL(Dbg_ver_def_title(ofl->ofl_lml, ofl->ofl_name)); /* * First check if there are any cyclic dependency */ for (APLIST_TRAVERSE(ofl->ofl_verdesc, idx1, vdp)) if ((is_cyclic = vers_visit_children(ofl, vdp, 0)) == S_ERROR) return (S_ERROR); if (is_cyclic) ofl->ofl_flags |= FLG_OF_FATAL; for (APLIST_TRAVERSE(ofl->ofl_verdesc, idx1, vdp)) { uint8_t cnt; Elf64_Sym *sym; Sym_desc *sdp; const char *name = vdp->vd_name; unsigned char bind; Ver_desc *_vdp; avl_index_t where; size_t idx2; if (vdp->vd_ndx == 0) { ld_eprintf(ofl, ERR_FATAL, (MSG_VER_UNDEF), name, vdp->vd_ref->vd_name, vdp->vd_ref->vd_file->ifl_name); continue; } //DBG_CALL(Dbg_ver_desc_entry(ofl->ofl_lml, vdp)); /* * If a version definition contains no symbols this is possibly * a mapfile error. */ #if 0 if ((vdp->vd_flags & (VER_FLG_BASE | VER_FLG_WEAK | FLG_VER_REFER)) == 0) DBG_CALL(Dbg_ver_nointerface(ofl->ofl_lml, vdp->vd_name)); #endif /* * Update the version entry count to account for this new * version descriptor (the count is the size in bytes). */ ofl->ofl_verdefsz += sizeof (Elf64_Verdef); /* * Traverse this versions dependency list to determine what * additional version dependencies we must account for against * this descriptor. */ cnt = 1; for (APLIST_TRAVERSE(vdp->vd_deps, idx2, _vdp)) { #if defined(__lint) /* get lint to think `_vdp' is used... */ vdp = _vdp; #endif cnt++; } ofl->ofl_verdefsz += (cnt * sizeof (Elf64_Verdaux)); /* * Except for the base version descriptor, generate an absolute * symbol to reflect this version. */ if (vdp->vd_flags & VER_FLG_BASE) continue; if (vdp->vd_flags & VER_FLG_WEAK) bind = STB_WEAK; else bind = STB_GLOBAL; if (sdp = ld_sym_find(name, vdp->vd_hash, &where, ofl)) { /* * If the symbol already exists and is undefined or was * defined in a shared library, convert it to an * absolute. */ if ((sdp->sd_sym->st_shndx == SHN_UNDEF) || (sdp->sd_ref != REF_REL_NEED)) { sdp->sd_shndx = sdp->sd_sym->st_shndx = SHN_ABS; sdp->sd_sym->st_info = ELF_ST_INFO(bind, STT_OBJECT); sdp->sd_ref = REF_REL_NEED; sdp->sd_flags |= (FLG_SY_SPECSEC | FLG_SY_DEFAULT | FLG_SY_EXPDEF); sdp->sd_aux->sa_overndx = vdp->vd_ndx; /* * If the reference originated from a mapfile * insure we mark the symbol as used. */ if (sdp->sd_flags & FLG_SY_MAPREF) sdp->sd_flags |= FLG_SY_MAPUSED; } else if ((sdp->sd_flags & FLG_SY_SPECSEC) && (sdp->sd_sym->st_shndx != SHN_ABS) && (sdp->sd_ref == REF_REL_NEED)) { ld_eprintf(ofl, ERR_WARNING, (MSG_VER_DEFINED), name, sdp->sd_file->ifl_name); } } else { /* * If the symbol does not exist create it. */ if ((sym = libld_calloc(sizeof (Elf64_Sym), 1)) == NULL) return (S_ERROR); sym->st_shndx = SHN_ABS; sym->st_info = ELF_ST_INFO(bind, STT_OBJECT); //DBG_CALL(Dbg_ver_symbol(ofl->ofl_lml, name)); if ((sdp = ld_sym_enter(name, sym, vdp->vd_hash, vdp->vd_file, ofl, 0, SHN_ABS, (FLG_SY_SPECSEC | FLG_SY_DEFAULT | FLG_SY_EXPDEF), &where)) == (Sym_desc *)S_ERROR) return (S_ERROR); sdp->sd_ref = REF_REL_NEED; sdp->sd_aux->sa_overndx = vdp->vd_ndx; } } return (1); }