#define ELF_TARGET_AMD64
#include <stdio.h>
#include <debug.h>
#include "msg.h"
#include "_libld.h"
typedef enum {
SYM_DEFINED,
SYM_UNDEFINED,
SYM_TENTATIVE,
SYM_NUM
} Symtype;
static void
sym_null(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
int ndx, Word nshndx, sd_flag_t nsdflags)
{
}
static void
sym_visibility_diag(Error err, Sym_desc *sdp, Sym *osym, Sym *nsym,
Ifl_desc *ifl, Ofl_desc *ofl)
{
Conv_inv_buf_t inv_obuf, inv_nbuf;
if (!(ofl->ofl_flags & FLG_OF_VERBOSE) && (err != ERR_FATAL))
return;
ld_eprintf(ofl, err, MSG_INTL(MSG_SYM_CONFVIS), demangle(sdp->sd_name));
ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_VISTYPES),
sdp->sd_file->ifl_name, conv_sym_other(osym->st_other, &inv_obuf),
ifl->ifl_name, conv_sym_other(nsym->st_other, &inv_nbuf));
if (err != ERR_FATAL)
ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
ifl->ifl_name);
}
static Half
sym_visibility(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl)
{
Sym *osym = sdp->sd_sym;
uchar_t wovis, ovis;
uchar_t wnvis, nvis;
wovis = ovis = ELF_ST_VISIBILITY(osym->st_other);
wnvis = nvis = ELF_ST_VISIBILITY(nsym->st_other);
if (wovis == STV_ELIMINATE)
wovis = STV_HIDDEN;
if (wnvis == STV_ELIMINATE)
wnvis = STV_HIDDEN;
if ((sdp->sd_ref == REF_REL_NEED) &&
(ifl->ifl_ehdr->e_type == ET_DYN)) {
if ((sdp->sd_sym->st_shndx == SHN_UNDEF) &&
(nsym->st_shndx != SHN_UNDEF) && (wnvis == STV_SINGLETON))
return (STV_SINGLETON);
else
return (ovis);
}
if ((sdp->sd_ref != REF_REL_NEED) &&
(ifl->ifl_ehdr->e_type == ET_REL)) {
if ((sdp->sd_sym->st_shndx != SHN_UNDEF) &&
(nsym->st_shndx == SHN_UNDEF) && (wovis == STV_SINGLETON))
return (STV_SINGLETON);
else
return (nvis);
}
if (wovis == wnvis) {
if (ovis == nvis)
return (nvis);
else
return (STV_ELIMINATE);
}
if ((wnvis == STV_EXPORTED) || (wnvis == STV_SINGLETON)) {
if ((wovis != STV_DEFAULT) && (wovis != STV_EXPORTED) &&
(wovis != STV_SINGLETON)) {
if (sdp->sd_flags & FLG_SY_MAPFILE) {
sym_visibility_diag(ERR_WARNING, sdp, osym,
nsym, ifl, ofl);
} else {
sym_visibility_diag(ERR_FATAL, sdp, osym,
nsym, ifl, ofl);
}
}
return (nvis);
}
if (wovis == STV_SINGLETON) {
if ((wnvis == STV_EXPORTED) || (wnvis == STV_DEFAULT))
return (STV_SINGLETON);
if (sdp->sd_flags & FLG_SY_MAPFILE) {
sym_visibility_diag(ERR_WARNING, sdp, osym,
nsym, ifl, ofl);
} else {
sym_visibility_diag(ERR_FATAL, sdp, osym,
nsym, ifl, ofl);
}
return (nvis);
}
if (wovis == STV_EXPORTED) {
if (wnvis == STV_SINGLETON)
return (STV_SINGLETON);
if (wnvis == STV_DEFAULT)
return (STV_EXPORTED);
if (sdp->sd_flags & FLG_SY_MAPFILE) {
sym_visibility_diag(ERR_WARNING, sdp, osym,
nsym, ifl, ofl);
} else {
sym_visibility_diag(ERR_FATAL, sdp, osym,
nsym, ifl, ofl);
}
return (nvis);
}
if ((wnvis == STV_INTERNAL) || (wovis == STV_INTERNAL)) {
if ((wnvis == STV_INTERNAL) &&
(sdp->sd_flags & FLG_SY_MAPFILE)) {
sym_visibility_diag(ERR_WARNING, sdp, osym, nsym,
ifl, ofl);
}
return (STV_INTERNAL);
} else if ((wnvis == STV_HIDDEN) || (wovis == STV_HIDDEN)) {
if ((wnvis == STV_HIDDEN) &&
(sdp->sd_flags & FLG_SY_MAPFILE)) {
sym_visibility_diag(ERR_WARNING, sdp, osym, nsym,
ifl, ofl);
}
if ((ovis == STV_ELIMINATE) || (nvis == STV_ELIMINATE))
return (STV_ELIMINATE);
else
return (STV_HIDDEN);
} else if ((wnvis == STV_PROTECTED) || (wovis == STV_PROTECTED))
return (STV_PROTECTED);
return (STV_DEFAULT);
}
static void
sym_typecheck(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
int ndx, Word nshndx, sd_flag_t nsdflags)
{
uchar_t otype = ELF_ST_TYPE(sdp->sd_sym->st_info);
uchar_t ntype = ELF_ST_TYPE(nsym->st_info);
Conv_inv_buf_t inv_buf1, inv_buf2;
if ((ld_targ.t_ms.ms_mach_sym_typecheck != NULL) &&
(*ld_targ.t_ms.ms_mach_sym_typecheck)(sdp, nsym, ifl, ofl))
return;
if ((otype == ntype) || (otype == STT_NOTYPE) || (ntype == STT_NOTYPE))
return;
ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
demangle(sdp->sd_name));
ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
sdp->sd_file->ifl_name,
conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype, 0, &inv_buf1),
ifl->ifl_name,
conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype, 0, &inv_buf2));
}
static void
sym_mach_check(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
int ndx, Word nshndx, sd_flag_t nsdflags)
{
if (ld_targ.t_ms.ms_mach_sym_typecheck != NULL)
(void) (*ld_targ.t_ms.ms_mach_sym_typecheck)(sdp, nsym,
ifl, ofl);
}
static void
sym_promote(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
int ndx, Word nshndx, sd_flag_t nsdflags)
{
Word shndx = nsym->st_shndx;
sym_typecheck(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
if ((sdp->sd_ref == REF_DYN_SEEN) &&
(ifl->ifl_ehdr->e_type == ET_REL)) {
sdp->sd_ref = REF_DYN_NEED;
if (shndx == SHN_UNDEF)
sdp->sd_aux->sa_rfile = ifl->ifl_name;
if (((shndx == SHN_UNDEF) || ((nsdflags & FLG_SY_SPECSEC) &&
(shndx == SHN_COMMON))) &&
(ELF_ST_BIND(nsym->st_info) == STB_GLOBAL))
sdp->sd_flags |= FLG_SY_GLOBREF;
}
}
static void
sym_override(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
int ndx, Word nshndx, sd_flag_t nsdflags)
{
Sym *osym = sdp->sd_sym;
Word link;
if ((ELF_ST_BIND(osym->st_info) == STB_WEAK) &&
(sdp->sd_sym->st_shndx == SHN_UNDEF) &&
((ifl->ifl_flags & FLG_IF_NEEDED) == 0))
return;
sym_typecheck(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
if ((sdp->sd_flags & FLG_SY_SOFOUND) &&
(ifl->ifl_ehdr->e_type == ET_DYN))
return;
sdp->sd_flags &= ~FLG_SY_NOTAVAIL;
*osym = *nsym;
sdp->sd_shndx = nshndx;
sdp->sd_flags &= ~FLG_SY_SPECSEC;
sdp->sd_flags |= (nsdflags & (FLG_SY_SPECSEC | FLG_SY_TENTSYM));
if (ELF_ST_VISIBILITY(nsym->st_other) == STV_PROTECTED)
sdp->sd_flags |= FLG_SY_PROT;
else
sdp->sd_flags &= ~FLG_SY_PROT;
if (ifl->ifl_ehdr->e_type == ET_REL) {
sdp->sd_ref = REF_REL_NEED;
if (nsym->st_shndx == SHN_UNDEF) {
if ((sdp->sd_flags & FLG_SY_MAPREF) == 0)
sdp->sd_aux->sa_rfile = ifl->ifl_name;
} else {
if ((ofl->ofl_flags1 & FLG_OF1_ALNODIR) &&
((sdp->sd_flags &
(FLG_SY_PROTECT | FLG_SY_DIR)) == 0))
sdp->sd_flags |= FLG_SY_NDIR;
}
if (((nsym->st_shndx == SHN_UNDEF) ||
((nsdflags & FLG_SY_SPECSEC) &&
(nsym->st_shndx == SHN_COMMON))) &&
(ELF_ST_BIND(nsym->st_info) == STB_GLOBAL))
sdp->sd_flags |= FLG_SY_GLOBREF;
else
sdp->sd_flags &= ~FLG_SY_GLOBREF;
} else {
if (sdp->sd_ref == REF_REL_NEED)
sdp->sd_ref = REF_DYN_NEED;
if (ifl->ifl_vercnt) {
Ver_index *vip;
Half vndx = ifl->ifl_versym[ndx];
sdp->sd_aux->sa_dverndx = vndx;
vip = &ifl->ifl_verndx[vndx];
if (!(vip->vi_flags & FLG_VER_AVAIL)) {
sdp->sd_flags |= FLG_SY_NOTAVAIL;
if (!(sdp->sd_aux->sa_vfile))
sdp->sd_aux->sa_vfile = ifl->ifl_name;
}
}
if (!(ifl->ifl_flags & FLG_IF_NEEDED))
sdp->sd_flags |= FLG_SY_NOTAVAIL;
}
if ((link = sdp->sd_aux->sa_linkndx) != 0) {
Sym_desc * _sdp;
_sdp = sdp->sd_file->ifl_oldndx[link];
_sdp->sd_aux->sa_linkndx = 0;
sdp->sd_aux->sa_linkndx = 0;
}
sdp->sd_file = ifl;
if (((nsdflags & FLG_SY_SPECSEC) == 0) &&
(nsym->st_shndx != SHN_UNDEF) &&
((sdp->sd_isc = ifl->ifl_isdesc[nshndx]) == NULL))
ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_NOSECDEF),
demangle(sdp->sd_name), ifl->ifl_name);
}
static void
sym_twoundefs(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
int ndx, Word nshndx, sd_flag_t nsdflags)
{
Sym *osym = sdp->sd_sym;
uchar_t obind = ELF_ST_BIND(osym->st_info);
uchar_t otype = ELF_ST_TYPE(osym->st_info);
uchar_t nbind = ELF_ST_BIND(nsym->st_info);
uchar_t ntype = ELF_ST_TYPE(nsym->st_info);
if (((obind == STB_WEAK) && (nbind != STB_WEAK)) ||
(otype == STT_NOTYPE) && (ntype != STT_NOTYPE)) {
sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
return;
}
sym_typecheck(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
}
static void
sym_tworeals(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
int ndx, Word nshndx, sd_flag_t nsdflags)
{
Conv_inv_buf_t inv_buf1, inv_buf2;
Sym *osym = sdp->sd_sym;
uchar_t otype = ELF_ST_TYPE(osym->st_info);
uchar_t obind = ELF_ST_BIND(osym->st_info);
uchar_t ntype = ELF_ST_TYPE(nsym->st_info);
uchar_t nbind = ELF_ST_BIND(nsym->st_info);
Half ofile = sdp->sd_file->ifl_ehdr->e_type;
Half nfile = ifl->ifl_ehdr->e_type;
int warn = 0;
if ((ofile == ET_REL) && (nfile == ET_REL) && (obind != STB_WEAK) &&
(nbind != STB_WEAK) && (!(ofl->ofl_flags & FLG_OF_MULDEFS))) {
ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_MULDEF),
demangle(sdp->sd_name));
ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
sdp->sd_file->ifl_name,
conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype,
0, &inv_buf1), ifl->ifl_name,
conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype,
0, &inv_buf2));
return;
}
if ((ld_targ.t_ms.ms_mach_sym_typecheck != NULL) &&
(*ld_targ.t_ms.ms_mach_sym_typecheck)(sdp, nsym, ifl, ofl))
return;
if (otype != ntype) {
ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
demangle(sdp->sd_name));
ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
sdp->sd_file->ifl_name,
conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype,
0, &inv_buf1), ifl->ifl_name,
conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype,
0, &inv_buf2));
warn++;
} else if ((otype == STT_OBJECT) && (osym->st_size != nsym->st_size)) {
if (!(ofl->ofl_flags & FLG_OF_NOWARN)) {
ld_eprintf(ofl, ERR_WARNING,
MSG_INTL(MSG_SYM_DIFFATTR), demangle(sdp->sd_name),
MSG_INTL(MSG_STR_SIZES), sdp->sd_file->ifl_name,
EC_XWORD(osym->st_size), ifl->ifl_name,
EC_XWORD(nsym->st_size));
warn++;
}
}
if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN)) {
if (warn)
ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
sdp->sd_file->ifl_name);
return;
} else if ((nfile == ET_REL) && ((ofile == ET_DYN) ||
((obind == STB_WEAK) && (nbind != STB_WEAK)))) {
if (warn)
ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
ifl->ifl_name);
sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
return;
} else {
if (warn)
ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
sdp->sd_file->ifl_name);
sym_promote(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
return;
}
}
static void
sym_realtent(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
int ndx, Word nshndx, sd_flag_t nsdflags)
{
Conv_inv_buf_t inv_buf1, inv_buf2;
Sym *osym = sdp->sd_sym;
uchar_t otype = ELF_ST_TYPE(osym->st_info);
uchar_t obind = ELF_ST_BIND(osym->st_info);
uchar_t ntype = ELF_ST_TYPE(nsym->st_info);
uchar_t nbind = ELF_ST_BIND(nsym->st_info);
Boolean otent = FALSE, ntent = FALSE;
Half ofile = sdp->sd_file->ifl_ehdr->e_type;
Half nfile = ifl->ifl_ehdr->e_type;
int warn = 0;
uchar_t ovis = ELF_ST_VISIBILITY(osym->st_other);
uchar_t nvis = ELF_ST_VISIBILITY(nsym->st_other);
if ((ofile == ET_REL) && (nfile == ET_REL) && (obind == nbind) &&
((otype == STT_FUNC) || (ntype == STT_FUNC))) {
if (ofl->ofl_flags & FLG_OF_MULDEFS) {
ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
demangle(sdp->sd_name));
sym_promote(sdp, nsym, ifl, ofl, ndx,
nshndx, nsdflags);
} else {
ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_MULDEF),
demangle(sdp->sd_name));
}
ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
sdp->sd_file->ifl_name,
conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype,
0, &inv_buf1), ifl->ifl_name,
conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype,
0, &inv_buf2));
return;
} else if (ofile != nfile) {
if ((ofile == ET_DYN) && (otype == STT_FUNC)) {
if ((otype != STB_WEAK) && (ntype == STB_WEAK))
return;
else {
sym_override(sdp, nsym, ifl, ofl, ndx,
nshndx, nsdflags);
return;
}
}
if ((nfile == ET_DYN) && (ntype == STT_FUNC)) {
if ((ntype != STB_WEAK) && (otype == STB_WEAK)) {
sym_override(sdp, nsym, ifl, ofl, ndx,
nshndx, nsdflags);
return;
} else
return;
}
}
if (sdp->sd_flags & FLG_SY_TENTSYM)
otent = TRUE;
if (nsdflags & FLG_SY_TENTSYM)
ntent = TRUE;
if (otype != ntype) {
ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
demangle(sdp->sd_name));
ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
sdp->sd_file->ifl_name,
conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype,
0, &inv_buf1), ifl->ifl_name,
conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype,
0, &inv_buf2));
warn++;
} else if (osym->st_size != nsym->st_size) {
if (((ofile == ET_REL) && (nfile == ET_REL) &&
(obind == nbind)) &&
((otent && (osym->st_size > nsym->st_size)) ||
(ntent && (osym->st_size < nsym->st_size)))) {
ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_DIFFATTR),
demangle(sdp->sd_name), MSG_INTL(MSG_STR_SIZES),
sdp->sd_file->ifl_name, EC_XWORD(osym->st_size),
ifl->ifl_name, EC_XWORD(nsym->st_size));
ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_TENTERR));
} else {
if (!(ofl->ofl_flags & FLG_OF_NOWARN)) {
ld_eprintf(ofl, ERR_WARNING,
MSG_INTL(MSG_SYM_DIFFATTR),
demangle(sdp->sd_name),
MSG_INTL(MSG_STR_SIZES),
sdp->sd_file->ifl_name,
EC_XWORD(osym->st_size),
ifl->ifl_name, EC_XWORD(nsym->st_size));
warn++;
}
}
}
if ((ofile == ET_REL) && (nfile == ET_DYN) && (otent == TRUE) &&
(ovis == STV_PROTECTED)) {
return;
}
if ((ofile == ET_DYN) && (nfile == ET_REL) && (ntent == TRUE) &&
(nvis == STV_PROTECTED)) {
sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
return;
}
if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN)) {
if (warn)
ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
sdp->sd_file->ifl_name);
return;
}
if (((otent) && (!((obind != STB_WEAK) && (nbind == STB_WEAK)))) ||
((obind == STB_WEAK) && (nbind != STB_WEAK))) {
if (warn)
ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
ifl->ifl_name);
sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
return;
} else {
if (warn)
ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
sdp->sd_file->ifl_name);
sym_promote(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
return;
}
}
static void
sym_twotent(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
int ndx, Word nshndx, sd_flag_t nsdflags)
{
Sym *osym = sdp->sd_sym;
uchar_t obind = ELF_ST_BIND(osym->st_info);
uchar_t nbind = ELF_ST_BIND(nsym->st_info);
Half ofile = sdp->sd_file->ifl_ehdr->e_type;
Half nfile = ifl->ifl_ehdr->e_type;
size_t size = 0;
Xword value = 0;
#if defined(_ELF64)
if (ld_targ.t_m.m_mach == EM_AMD64) {
if ((sdp->sd_sym->st_shndx == SHN_COMMON) &&
(nsym->st_shndx == SHN_X86_64_LCOMMON)) {
return;
} else if ((sdp->sd_sym->st_shndx == SHN_X86_64_LCOMMON) &&
(nsym->st_shndx == SHN_COMMON)) {
sym_override(sdp, nsym, ifl, ofl, ndx, nshndx,
nsdflags);
return;
}
}
#endif
if ((osym->st_value != nsym->st_value) &&
((sdp->sd_flags & FLG_SY_SPECSEC) &&
(sdp->sd_sym->st_shndx == SHN_COMMON) &&
(nsdflags & FLG_SY_SPECSEC) &&
#if defined(_ELF64)
(nsym->st_shndx == SHN_COMMON)) ||
((ld_targ.t_m.m_mach == EM_AMD64) &&
(sdp->sd_flags & FLG_SY_SPECSEC) &&
(sdp->sd_sym->st_shndx == SHN_X86_64_LCOMMON) &&
(nsdflags & FLG_SY_SPECSEC) &&
(nsym->st_shndx == SHN_X86_64_LCOMMON))) {
#else
(nsym->st_shndx == SHN_COMMON))) {
#endif
const char *emsg = MSG_INTL(MSG_SYM_DEFTAKEN);
const char *file;
Xword salign;
Xword balign;
uint_t alignscompliment;
if (osym->st_value < nsym->st_value) {
salign = osym->st_value;
balign = nsym->st_value;
} else {
salign = nsym->st_value;
balign = osym->st_value;
}
if (S_ALIGN(balign, salign) == balign)
alignscompliment = 1;
else
alignscompliment = 0;
if (!(ofl->ofl_flags & FLG_OF_NOWARN) && !alignscompliment)
ld_eprintf(ofl, ERR_WARNING,
MSG_INTL(MSG_SYM_DIFFATTR), demangle(sdp->sd_name),
MSG_INTL(MSG_STR_ALIGNMENTS),
sdp->sd_file->ifl_name, EC_XWORD(osym->st_value),
ifl->ifl_name, EC_XWORD(nsym->st_value));
if ((obind == STB_WEAK) && (nbind != STB_WEAK))
file = ifl->ifl_name;
else if (obind != nbind)
file = sdp->sd_file->ifl_name;
else {
emsg = MSG_INTL(MSG_SYM_LARGER);
value = balign;
}
if (!(ofl->ofl_flags & FLG_OF_NOWARN) && !alignscompliment)
ld_eprintf(ofl, ERR_NONE, emsg, file);
}
if (osym->st_size != nsym->st_size) {
const char *emsg = MSG_INTL(MSG_SYM_DEFTAKEN);
const char *file;
if (!(ofl->ofl_flags & FLG_OF_NOWARN))
ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFATTR),
demangle(sdp->sd_name), MSG_INTL(MSG_STR_SIZES),
sdp->sd_file->ifl_name, EC_XWORD(osym->st_size),
ifl->ifl_name, EC_XWORD(nsym->st_size));
if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN)) {
if (!(ofl->ofl_flags & FLG_OF_NOWARN))
ld_eprintf(ofl, ERR_NONE, emsg,
sdp->sd_file->ifl_name);
return;
}
if (nfile != ofile) {
if (nfile == ET_REL) {
file = ifl->ifl_name;
if (osym->st_size > nsym->st_size) {
size = (size_t)osym->st_size;
emsg = MSG_INTL(MSG_SYM_DEFUPDATE);
}
sym_override(sdp, nsym, ifl, ofl, ndx,
nshndx, nsdflags);
} else {
file = sdp->sd_file->ifl_name;
if (osym->st_size < nsym->st_size) {
size = (size_t)nsym->st_size;
emsg = MSG_INTL(MSG_SYM_DEFUPDATE);
}
sym_promote(sdp, nsym, ifl, ofl, ndx,
nshndx, nsdflags);
}
} else if (obind != nbind) {
if ((obind == STB_WEAK) && (nbind != STB_WEAK)) {
sym_override(sdp, nsym, ifl, ofl, ndx,
nshndx, nsdflags);
file = ifl->ifl_name;
} else
file = sdp->sd_file->ifl_name;
} else {
if (osym->st_size < nsym->st_size) {
sym_override(sdp, nsym, ifl, ofl, ndx,
nshndx, nsdflags);
file = ifl->ifl_name;
} else
file = sdp->sd_file->ifl_name;
}
if (!(ofl->ofl_flags & FLG_OF_NOWARN))
ld_eprintf(ofl, ERR_NONE, emsg, file);
if (size)
sdp->sd_sym->st_size = (Xword)size;
} else {
if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN))
return;
else if (((ofile != nfile) && (nfile == ET_REL)) ||
(((obind == STB_WEAK) && (nbind != STB_WEAK)) &&
(!((ofile != nfile) && (ofile == ET_REL)))))
sym_override(sdp, nsym, ifl, ofl, ndx,
nshndx, nsdflags);
else
sym_promote(sdp, nsym, ifl, ofl, ndx,
nshndx, nsdflags);
}
if (value)
sdp->sd_sym->st_value = value;
}
static void (*Action[REF_NUM * SYM_NUM * 2][SYM_NUM])(Sym_desc *,
Sym *, Ifl_desc *, Ofl_desc *, int, Word, sd_flag_t) = {
sym_tworeals, sym_promote, sym_realtent,
sym_override, sym_override, sym_override,
sym_realtent, sym_promote, sym_twotent,
sym_tworeals, sym_typecheck, sym_realtent,
sym_override, sym_override, sym_override,
sym_realtent, sym_typecheck, sym_twotent,
sym_tworeals, sym_typecheck, sym_realtent,
sym_override, sym_twoundefs, sym_override,
sym_realtent, sym_null, sym_twotent,
sym_tworeals, sym_null, sym_realtent,
sym_override, sym_mach_check, sym_override,
sym_realtent, sym_null, sym_twotent,
sym_tworeals, sym_null, sym_realtent,
sym_override, sym_null, sym_override,
sym_realtent, sym_null, sym_twotent,
sym_tworeals, sym_null, sym_realtent,
sym_override, sym_mach_check, sym_override,
sym_realtent, sym_null, sym_twotent
};
uintptr_t
ld_sym_resolve(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl, int ndx,
Word nshndx, sd_flag_t nsdflags)
{
int row, column;
Sym *osym = sdp->sd_sym;
sd_flag_t osdflags = sdp->sd_flags;
Is_desc *isp;
Half vis = 0, nfile = ifl->ifl_ehdr->e_type;
Half oref = sdp->sd_ref;
if (osdflags & FLG_SY_TENTSYM)
row = SYM_TENTATIVE;
else if ((sdp->sd_sym->st_shndx == SHN_UNDEF) ||
(sdp->sd_sym->st_shndx == SHN_SUNW_IGNORE))
row = SYM_UNDEFINED;
else
row = SYM_DEFINED;
if ((nfile == ET_DYN) && !(ifl->ifl_flags & FLG_IF_NEEDED) &&
(row != SYM_UNDEFINED))
return (1);
row = row + (REF_NUM * sdp->sd_ref);
if (nfile == ET_DYN)
row += (REF_NUM * SYM_NUM);
if ((oref == REF_REL_NEED) || (nfile == ET_REL))
vis = sym_visibility(sdp, nsym, ifl, ofl);
if ((nsdflags & FLG_SY_SPECSEC) &&
(nsym->st_shndx == SHN_COMMON)) {
column = SYM_TENTATIVE;
nsdflags |= FLG_SY_TENTSYM;
#if defined(_ELF64)
} else if ((ld_targ.t_m.m_mach == EM_AMD64) &&
(nsdflags & FLG_SY_SPECSEC) &&
(nsym->st_shndx == SHN_X86_64_LCOMMON)) {
column = SYM_TENTATIVE;
nsdflags |= FLG_SY_TENTSYM;
#endif
} else if ((nsym->st_shndx == SHN_UNDEF) ||
(nsym->st_shndx == SHN_SUNW_IGNORE)) {
column = SYM_UNDEFINED;
nshndx = SHN_UNDEF;
} else {
column = SYM_DEFINED;
if (((nsdflags & FLG_SY_SPECSEC) == 0) && (nfile == ET_DYN)) {
isp = ifl->ifl_isdesc[nshndx];
if (isp && (isp->is_shdr->sh_type == SHT_NOBITS)) {
column = SYM_TENTATIVE;
nsdflags |= FLG_SY_TENTSYM;
}
}
}
DBG_CALL(Dbg_syms_resolving(ofl, ndx, sdp->sd_name, row, column,
osym, nsym, sdp, ifl));
if ((ofl->ofl_flags & FLG_OF_GENMAP) && (nsym->st_shndx != SHN_UNDEF) &&
((nsdflags & FLG_SY_SPECSEC) == 0))
if (aplist_append(&sdp->sd_aux->sa_dfiles, ifl->ifl_name,
AL_CNT_SDP_DFILES) == NULL)
return (S_ERROR);
Action[row][column](sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
if ((oref == REF_REL_NEED) || (nfile == ET_REL)) {
if ((vis == STV_EXPORTED) || (vis == STV_SINGLETON)) {
sdp->sd_flags &= ~MSK_SY_LOCAL;
if (vis == STV_EXPORTED)
sdp->sd_flags |= FLG_SY_EXPORT;
else {
sdp->sd_flags |= (FLG_SY_NDIR | FLG_SY_SINGLE);
if (sdp->sd_ref == REF_REL_NEED) {
ofl->ofl_flags1 |=
(FLG_OF1_NDIRECT | FLG_OF1_NGLBDIR);
}
}
} else if (vis == STV_PROTECTED) {
sdp->sd_flags |= FLG_SY_PROTECT;
} else if ((vis == STV_INTERNAL) || (vis == STV_HIDDEN)) {
sdp->sd_flags |= FLG_SY_HIDDEN;
} else if (vis == STV_ELIMINATE) {
sdp->sd_flags |= (FLG_SY_HIDDEN | FLG_SY_ELIM);
}
sdp->sd_sym->st_other =
(sdp->sd_sym->st_other & ~MSK_SYM_VISIBILITY) | vis;
}
if ((sdp->sd_file == ifl) && (nfile == ET_REL) && (ifl->ifl_versym) &&
(nsym->st_shndx != SHN_UNDEF))
ld_vers_promote(sdp, ndx, ifl, ofl);
if ((nfile == ET_REL) && ((sdp->sd_flags &
(FLG_SY_MAPREF | FLG_SY_MAPUSED)) == FLG_SY_MAPREF)) {
if ((sdp->sd_flags & (FLG_SY_EXTERN | FLG_SY_PARENT)) ||
((sdp->sd_sym->st_shndx != SHN_UNDEF) &&
(sdp->sd_ref == REF_REL_NEED)))
sdp->sd_flags |= FLG_SY_MAPUSED;
}
if ((osdflags & FLG_SY_CAP) || (nsdflags & FLG_SY_CAP))
sdp->sd_flags |= FLG_SY_CAP;
DBG_CALL(Dbg_syms_resolved(ofl, sdp));
return (1);
}