#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <ctype.h>
#include <elfcap.h>
#include <debug.h>
#include "msg.h"
#include "_libld.h"
#include "_map.h"
static Boolean
map_cap(Mapfile *mf, Word type, Capmask *capmask)
{
Token tok;
Xword number;
int used = 0;
Ofl_desc *ofl = mf->mf_ofl;
ld_map_tkval_t tkv;
elfcap_mask_t value = 0;
if (DBG_ENABLED) {
Dbg_cap_mapfile_title(ofl->ofl_lml, mf->mf_lineno);
Dbg_cap_val_entry(ofl->ofl_lml, DBG_STATE_CURRENT, CA_SUNW_HW_1,
capmask->cm_val, ld_targ.t_m.m_mach);
}
while ((tok = ld_map_gettoken(mf, TK_F_STRLC, &tkv)) !=
TK_SEMICOLON) {
if (tok != TK_STRING) {
if (tok != TK_ERROR)
mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSEGATT));
return (FALSE);
}
if (strncmp(tkv.tkv_str, MSG_ORIG(MSG_MAP_OVERRIDE),
MSG_MAP_OVERRIDE_SIZE) == 0) {
ld_map_cap_set_ovflag(mf, type);
used++;
continue;
}
if ((number = (Xword)elfcap_tag_from_str(ELFCAP_STYLE_LC,
type, tkv.tkv_str, ld_targ.t_m.m_mach)) != 0) {
value |= number;
used++;
continue;
}
if (tkv.tkv_str[0] == 'v') {
if (ld_map_strtoxword(&tkv.tkv_str[1], NULL,
&number) != STRTOXWORD_OK) {
mf_fatal(mf, MSG_INTL(MSG_MAP_BADCAPVAL),
tkv.tkv_str);
return (FALSE);
}
value |= number;
used++;
continue;
}
used++;
mf_fatal(mf, MSG_INTL(MSG_MAP_UNKCAPATTR), tkv.tkv_str);
return (FALSE);
}
if (used == 0) {
mf_warn0(mf, MSG_INTL(MSG_MAP_EMPTYCAP));
return (TRUE);
}
DBG_CALL(Dbg_cap_val_entry(ofl->ofl_lml, DBG_STATE_NEW, type, value,
ld_targ.t_m.m_mach));
capmask->cm_val |= value;
if (!ld_map_cap_sanitize(mf, type, capmask))
return (FALSE);
return (TRUE);
}
static Boolean
map_equal_flags(Mapfile *mf, Sg_desc *sgp, Boolean *b_flags,
const char *flag_tok)
{
Word tmp_flags = 0;
if (*b_flags) {
mf_fatal(mf, MSG_INTL(MSG_MAP_MOREONCE),
MSG_INTL(MSG_MAP_SEGFLAG));
return (FALSE);
}
flag_tok++;
while (*flag_tok) {
switch (*flag_tok) {
case 'r':
tmp_flags |= PF_R;
break;
case 'w':
tmp_flags |= PF_W;
break;
case 'x':
tmp_flags |= PF_X;
break;
case 'e':
sgp->sg_flags |= FLG_SG_EMPTY;
break;
case 'o':
if (aplist_nitems(sgp->sg_is_order) > 0) {
mf_fatal(mf, MSG_INTL(MSG_MAP_ISORDVER),
sgp->sg_name);
return (FALSE);
}
sgp->sg_flags |= FLG_SG_IS_ORDER;
break;
case 'n':
sgp->sg_flags |= FLG_SG_NOHDR;
break;
default:
mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSEGFLG), *flag_tok);
return (FALSE);
}
flag_tok++;
}
if ((sgp->sg_flags & FLG_SG_P_FLAGS) &&
(sgp->sg_phdr.p_flags != tmp_flags) &&
!(sgp->sg_phdr.p_type == PT_LOAD &&
(tmp_flags & (PF_R|PF_W)) == (PF_R|PF_W) &&
(tmp_flags ^ sgp->sg_phdr.p_flags) == PF_X))
mf_warn(mf, MSG_INTL(MSG_MAP_REDEFATT),
MSG_INTL(MSG_MAP_SEGFLAG), sgp->sg_name);
sgp->sg_flags |= FLG_SG_P_FLAGS;
sgp->sg_phdr.p_flags = tmp_flags;
*b_flags = TRUE;
return (TRUE);
}
static Boolean
valuetoxword(Mapfile *mf, ld_map_tkval_t *tkv, Xword *value)
{
switch (ld_map_strtoxword(&tkv->tkv_str[1], NULL, value)) {
case STRTOXWORD_OK:
return (TRUE);
case STRTOXWORD_TOOBIG:
mf_fatal(mf, MSG_INTL(MSG_MAP_SEGADDR), tkv->tkv_str,
MSG_INTL(MSG_MAP_EXCLIMIT));
break;
default:
mf_fatal(mf, MSG_INTL(MSG_MAP_SEGADDR), tkv->tkv_str,
MSG_INTL(MSG_MAP_NOBADFRM));
break;
}
return (FALSE);
}
static Boolean
map_equal(Mapfile *mf, Sg_desc *sgp)
{
typedef struct {
const char *name;
Word p_type;
sg_flags_t sg_flags;
} seg_types_t;
static seg_types_t seg_type_arr[] = {
{ MSG_ORIG(MSG_MAP_LOAD), PT_LOAD, FLG_SG_P_TYPE },
{ MSG_ORIG(MSG_MAP_STACK), PT_SUNWSTACK,
FLG_SG_P_TYPE | FLG_SG_EMPTY },
{ MSG_ORIG(MSG_MAP_NULL), PT_NULL, FLG_SG_P_TYPE },
{ MSG_ORIG(MSG_MAP_NOTE), PT_NOTE, FLG_SG_P_TYPE },
{ NULL }
};
seg_types_t *seg_type;
Token tok;
ld_map_tkval_t tkv;
Boolean b_type = FALSE;
Boolean b_flags = FALSE;
Boolean b_len = FALSE;
Boolean b_round = FALSE;
Boolean b_vaddr = FALSE;
Boolean b_paddr = FALSE;
Boolean b_align = FALSE;
while ((tok = ld_map_gettoken(mf, TK_F_STRLC, &tkv)) !=
TK_SEMICOLON) {
if (tok != TK_STRING) {
if (tok != TK_ERROR)
mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSEGATT));
return (FALSE);
}
for (seg_type = seg_type_arr; seg_type->name; seg_type++) {
if (strcmp(tkv.tkv_str, seg_type->name) == 0) {
if (b_type) {
mf_fatal(mf, MSG_INTL(MSG_MAP_MOREONCE),
MSG_INTL(MSG_MAP_SEGTYP));
return (FALSE);
}
if ((sgp->sg_flags & FLG_SG_P_TYPE) &&
(sgp->sg_phdr.p_type != seg_type->p_type)) {
mf_warn(mf, MSG_INTL(MSG_MAP_REDEFATT),
MSG_INTL(MSG_MAP_SEGTYP),
sgp->sg_name);
}
sgp->sg_phdr.p_type = seg_type->p_type;
sgp->sg_flags |= seg_type->sg_flags;
break;
}
}
if (seg_type->name != NULL)
continue;
if (*tkv.tkv_str == '?') {
if (!map_equal_flags(mf, sgp, &b_flags, tkv.tkv_str))
return (FALSE);
continue;
}
if ((tkv.tkv_str[0] == 'l') || (tkv.tkv_str[0] == 'v') ||
(tkv.tkv_str[0] == 'a') || (tkv.tkv_str[0] == 'p') ||
(tkv.tkv_str[0] == 'r')) {
Xword number;
if (!valuetoxword(mf, &tkv, &number))
return (FALSE);
switch (*tkv.tkv_str) {
case 'l':
if (b_len) {
mf_fatal(mf,
MSG_INTL(MSG_MAP_MOREONCE),
MSG_INTL(MSG_MAP_SEGLEN));
return (FALSE);
}
if ((sgp->sg_flags & FLG_SG_LENGTH) &&
(sgp->sg_length != number))
mf_warn(mf,
MSG_INTL(MSG_MAP_REDEFATT),
MSG_INTL(MSG_MAP_SEGLEN),
sgp->sg_name);
sgp->sg_length = number;
sgp->sg_flags |= FLG_SG_LENGTH;
b_len = TRUE;
break;
case 'r':
if (b_round) {
mf_fatal(mf,
MSG_INTL(MSG_MAP_MOREONCE),
MSG_INTL(MSG_MAP_SEGROUND));
return (FALSE);
}
if ((sgp->sg_flags & FLG_SG_ROUND) &&
(sgp->sg_round != number))
mf_warn(mf,
MSG_INTL(MSG_MAP_REDEFATT),
MSG_INTL(MSG_MAP_SEGROUND),
sgp->sg_name);
sgp->sg_round = number;
sgp->sg_flags |= FLG_SG_ROUND;
b_round = TRUE;
break;
case 'v':
if (b_vaddr) {
mf_fatal(mf,
MSG_INTL(MSG_MAP_MOREONCE),
MSG_INTL(MSG_MAP_SEGVADDR));
return (FALSE);
}
if ((sgp->sg_flags & FLG_SG_P_VADDR) &&
(sgp->sg_phdr.p_vaddr != number))
mf_warn(mf,
MSG_INTL(MSG_MAP_REDEFATT),
MSG_INTL(MSG_MAP_SEGVADDR),
sgp->sg_name);
sgp->sg_phdr.p_vaddr = (Addr)number;
sgp->sg_flags |= FLG_SG_P_VADDR;
b_vaddr = TRUE;
break;
case 'p':
if (b_paddr) {
mf_fatal(mf,
MSG_INTL(MSG_MAP_MOREONCE),
MSG_INTL(MSG_MAP_SEGPHYS));
return (FALSE);
}
if ((sgp->sg_flags & FLG_SG_P_PADDR) &&
(sgp->sg_phdr.p_paddr != number))
mf_warn(mf,
MSG_INTL(MSG_MAP_REDEFATT),
MSG_INTL(MSG_MAP_SEGPHYS),
sgp->sg_name);
sgp->sg_phdr.p_paddr = (Addr)number;
sgp->sg_flags |= FLG_SG_P_PADDR;
b_paddr = TRUE;
break;
case 'a':
if (b_align) {
mf_fatal(mf,
MSG_INTL(MSG_MAP_MOREONCE),
MSG_INTL(MSG_MAP_SEGALIGN));
return (FALSE);
}
if ((sgp->sg_flags & FLG_SG_P_ALIGN) &&
(sgp->sg_phdr.p_align != number))
mf_warn(mf,
MSG_INTL(MSG_MAP_REDEFATT),
MSG_INTL(MSG_MAP_SEGALIGN),
sgp->sg_name);
sgp->sg_phdr.p_align = (Xword)number;
sgp->sg_flags |= FLG_SG_P_ALIGN;
b_align = TRUE;
break;
}
continue;
}
mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSEGATT), tkv.tkv_str);
return (FALSE);
}
if ((sgp->sg_flags & FLG_SG_EMPTY) &&
(sgp->sg_phdr.p_type != PT_SUNWSTACK)) {
if (sgp->sg_phdr.p_flags != 0) {
mf_fatal(mf, MSG_INTL(MSG_MAP_SEGEMNOPERM),
EC_WORD(sgp->sg_phdr.p_flags));
return (FALSE);
}
if (sgp->sg_phdr.p_type == PT_LOAD) {
if ((mf->mf_ofl->ofl_flags & FLG_OF_EXEC) == 0) {
mf_fatal0(mf, MSG_INTL(MSG_MAP_SEGEMPEXE));
return (FALSE);
}
if ((sgp->sg_flags &
(FLG_SG_LENGTH | FLG_SG_P_VADDR)) !=
(FLG_SG_LENGTH | FLG_SG_P_VADDR)) {
mf_fatal0(mf, MSG_INTL(MSG_MAP_SEGEMPATT));
return (FALSE);
}
} else if (sgp->sg_phdr.p_type == PT_NULL) {
if ((sgp->sg_flags &
(FLG_SG_LENGTH | FLG_SG_P_VADDR)) &&
((sgp->sg_length != 0) ||
(sgp->sg_phdr.p_vaddr != 0))) {
mf_fatal0(mf, MSG_INTL(MSG_MAP_SEGEMPNOATT));
return (FALSE);
}
} else {
mf_warn0(mf, MSG_INTL(MSG_MAP_SEGEMPLOAD));
sgp->sg_phdr.p_type = PT_LOAD;
}
}
if ((sgp->sg_phdr.p_type != PT_NULL) &&
(sgp->sg_phdr.p_type != PT_LOAD)) {
const char *fmt;
if (sgp->sg_phdr.p_type == PT_SUNWSTACK)
fmt = MSG_INTL(MSG_MAP_NOSTACK1);
else
fmt = MSG_INTL(MSG_MAP_NONLOAD);
if ((sgp->sg_flags & FLG_SG_P_FLAGS) &&
(sgp->sg_phdr.p_type != PT_SUNWSTACK)) {
if (sgp->sg_phdr.p_flags != 0) {
mf_warn(mf, MSG_INTL(MSG_MAP_NONLOAD),
MSG_INTL(MSG_MAP_SEGFLAG));
sgp->sg_phdr.p_flags = 0;
}
}
if (sgp->sg_flags & FLG_SG_LENGTH)
if (sgp->sg_length != 0) {
mf_warn(mf, fmt, MSG_INTL(MSG_MAP_SEGLEN));
sgp->sg_length = 0;
}
if (sgp->sg_flags & FLG_SG_ROUND)
if (sgp->sg_round != 0) {
mf_warn(mf, fmt, MSG_INTL(MSG_MAP_SEGROUND));
sgp->sg_round = 0;
}
if (sgp->sg_flags & FLG_SG_P_VADDR) {
if (sgp->sg_phdr.p_vaddr != 0) {
mf_warn(mf, fmt, MSG_INTL(MSG_MAP_SEGVADDR));
sgp->sg_phdr.p_vaddr = 0;
}
}
if (sgp->sg_flags & FLG_SG_P_PADDR)
if (sgp->sg_phdr.p_paddr != 0) {
mf_warn(mf, fmt, MSG_INTL(MSG_MAP_SEGPHYS));
sgp->sg_phdr.p_paddr = 0;
}
if (sgp->sg_flags & FLG_SG_P_ALIGN)
if (sgp->sg_phdr.p_align != 0) {
mf_warn(mf, fmt, MSG_INTL(MSG_MAP_SEGALIGN));
sgp->sg_phdr.p_align = 0;
}
}
return (TRUE);
}
static Boolean
map_colon(Mapfile *mf, Ent_desc *enp)
{
Token tok;
ld_map_tkval_t tkv;
Boolean b_name = FALSE;
Boolean b_type = FALSE;
Boolean b_attr = FALSE;
Boolean b_bang = FALSE;
enp->ec_flags |= FLG_EC_CATCHALL;
while (((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_COLON) &&
(tok != TK_SEMICOLON)) {
if (tok == TK_ERROR)
return (FALSE);
if (tok != TK_STRING) {
mf_fatal0(mf, MSG_INTL(MSG_MAP_MALFORM));
return (FALSE);
}
if (*tkv.tkv_str == '$') {
if (b_type) {
mf_fatal(mf, MSG_INTL(MSG_MAP_MOREONCE),
MSG_INTL(MSG_MAP_SECTYP));
return (FALSE);
}
b_type = TRUE;
tkv.tkv_str++;
ld_map_lowercase(tkv.tkv_str);
if (strcmp(tkv.tkv_str, MSG_ORIG(MSG_STR_PROGBITS)) ==
0)
enp->ec_type = SHT_PROGBITS;
else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_STR_SYMTAB)) == 0)
enp->ec_type = SHT_SYMTAB;
else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_STR_DYNSYM)) == 0)
enp->ec_type = SHT_DYNSYM;
else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_STR_STRTAB)) == 0)
enp->ec_type = SHT_STRTAB;
else if ((strcmp(tkv.tkv_str,
MSG_ORIG(MSG_STR_REL)) == 0) ||
(strcmp(tkv.tkv_str, MSG_ORIG(MSG_STR_RELA)) == 0))
enp->ec_type = ld_targ.t_m.m_rel_sht_type;
else if (strcmp(tkv.tkv_str, MSG_ORIG(MSG_STR_HASH)) ==
0)
enp->ec_type = SHT_HASH;
else if (strcmp(tkv.tkv_str, MSG_ORIG(MSG_STR_LIB)) ==
0)
enp->ec_type = SHT_SHLIB;
else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_STR_LD_DYNAMIC)) == 0)
enp->ec_type = SHT_DYNAMIC;
else if (strcmp(tkv.tkv_str, MSG_ORIG(MSG_STR_NOTE)) ==
0)
enp->ec_type = SHT_NOTE;
else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_STR_NOBITS)) == 0)
enp->ec_type = SHT_NOBITS;
else {
mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSECTYP),
tkv.tkv_str);
return (FALSE);
}
enp->ec_flags &= ~FLG_EC_CATCHALL;
} else if (*tkv.tkv_str == '?') {
if (b_attr) {
mf_fatal(mf, MSG_INTL(MSG_MAP_MOREONCE),
MSG_INTL(MSG_MAP_SECFLAG));
return (FALSE);
}
b_attr = TRUE;
b_bang = FALSE;
tkv.tkv_str++;
ld_map_lowercase(tkv.tkv_str);
for (; *tkv.tkv_str != '\0'; tkv.tkv_str++)
switch (*tkv.tkv_str) {
case '!':
if (b_bang) {
mf_fatal(mf,
MSG_INTL(MSG_MAP_BADFLAG),
tkv.tkv_str);
return (FALSE);
}
b_bang = TRUE;
break;
case 'a':
if (enp->ec_attrmask & SHF_ALLOC) {
mf_fatal(mf,
MSG_INTL(MSG_MAP_BADFLAG),
tkv.tkv_str);
return (FALSE);
}
enp->ec_attrmask |= SHF_ALLOC;
if (!b_bang)
enp->ec_attrbits |= SHF_ALLOC;
b_bang = FALSE;
break;
case 'w':
if (enp->ec_attrmask & SHF_WRITE) {
mf_fatal(mf,
MSG_INTL(MSG_MAP_BADFLAG),
tkv.tkv_str);
return (FALSE);
}
enp->ec_attrmask |= SHF_WRITE;
if (!b_bang)
enp->ec_attrbits |= SHF_WRITE;
b_bang = FALSE;
break;
case 'x':
if (enp->ec_attrmask & SHF_EXECINSTR) {
mf_fatal(mf,
MSG_INTL(MSG_MAP_BADFLAG),
tkv.tkv_str);
return (FALSE);
}
enp->ec_attrmask |= SHF_EXECINSTR;
if (!b_bang)
enp->ec_attrbits |=
SHF_EXECINSTR;
b_bang = FALSE;
break;
default:
mf_fatal(mf,
MSG_INTL(MSG_MAP_BADFLAG),
tkv.tkv_str);
return (FALSE);
}
if (enp->ec_attrmask != 0)
enp->ec_flags &= ~FLG_EC_CATCHALL;
} else {
if (b_name) {
mf_fatal(mf, MSG_INTL(MSG_MAP_MOREONCE),
MSG_INTL(MSG_MAP_SECNAME));
return (FALSE);
}
b_name = TRUE;
enp->ec_is_name = tkv.tkv_str;
enp->ec_flags &= ~FLG_EC_CATCHALL;
}
}
if (tok == TK_COLON) {
while ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_SEMICOLON) {
Word ecf_type;
if (tok != TK_STRING) {
if (tok != TK_ERROR)
mf_fatal0(mf,
MSG_INTL(MSG_MAP_MALFORM));
return (FALSE);
}
if (tkv.tkv_str[0] == '*') {
ecf_type = TYP_ECF_BASENAME;
tkv.tkv_str++;
} else {
ecf_type = TYP_ECF_PATH;
}
if (!ld_map_seg_ent_files(mf, enp, ecf_type,
tkv.tkv_str))
return (FALSE);
enp->ec_flags &= ~FLG_EC_CATCHALL;
}
}
return (TRUE);
}
static Boolean
map_atsign(Mapfile *mf, Sg_desc *sgp)
{
Token tok;
ld_map_tkval_t tkv;
if ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_STRING) {
if (tok != TK_ERROR)
mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSYM_1));
return (FALSE);
}
if (!ld_map_seg_size_symbol(mf, sgp, TK_PLUSEQ, tkv.tkv_str))
return (FALSE);
if (ld_map_gettoken(mf, 0, &tkv) != TK_SEMICOLON) {
if (tok != TK_ERROR)
mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSCOL));
return (FALSE);
}
return (TRUE);
}
static Boolean
map_pipe(Mapfile *mf, Sg_desc *sgp)
{
Token tok;
ld_map_tkval_t tkv;
if ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_STRING) {
if (tok != TK_ERROR)
mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSEC));
return (FALSE);
}
if (!ld_map_seg_os_order_add(mf, sgp, tkv.tkv_str))
return (FALSE);
if ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_SEMICOLON) {
if (tok != TK_ERROR)
mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSCOL));
return (FALSE);
}
return (TRUE);
}
static Boolean
map_dash(Mapfile *mf, char *name)
{
Token tok;
Sdf_desc *sdf;
ld_map_tkval_t tkv;
enum {
MD_NONE = 0,
MD_ADDVERS,
} dolkey = MD_NONE;
if ((sdf = ld_map_dv(mf, name)) == NULL)
return (FALSE);
while ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_SEMICOLON) {
if ((tok != TK_STRING) && (tok != TK_EQUAL)) {
if (tok != TK_ERROR)
mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSO));
return (FALSE);
}
if (tok == TK_EQUAL) {
if ((tok = ld_map_gettoken(mf, 0, &tkv)) !=
TK_STRING) {
if (tok != TK_ERROR)
mf_fatal0(mf,
MSG_INTL(MSG_MAP_EXPSO));
return (FALSE);
}
switch (dolkey) {
case MD_ADDVERS:
if (!ld_map_dv_entry(mf, sdf, TRUE,
tkv.tkv_str))
return (FALSE);
break;
case MD_NONE:
mf_fatal(mf, MSG_INTL(MSG_MAP_UNEXTOK), '=');
return (FALSE);
}
dolkey = MD_NONE;
continue;
}
if (*tkv.tkv_str == '$') {
if (dolkey != MD_NONE) {
mf_fatal(mf, MSG_INTL(MSG_MAP_UNEXTOK), '$');
return (FALSE);
}
tkv.tkv_str++;
ld_map_lowercase(tkv.tkv_str);
if (strcmp(tkv.tkv_str, MSG_ORIG(MSG_MAP_ADDVERS)) ==
0) {
dolkey = MD_ADDVERS;
} else {
mf_fatal(mf, MSG_INTL(MSG_MAP_UNKSOTYP),
tkv.tkv_str);
return (FALSE);
}
continue;
}
if (!ld_map_dv_entry(mf, sdf, FALSE, tkv.tkv_str))
return (FALSE);
}
return (TRUE);
}
static Boolean
map_version(Mapfile *mf, char *name)
{
Token tok;
ld_map_tkval_t tkv;
ld_map_ver_t mv;
ld_map_sym_t ms;
Ofl_desc *ofl = mf->mf_ofl;
if (!ld_map_sym_ver_init(mf, name, &mv))
return (FALSE);
while ((tok = ld_map_gettoken(mf, 0, &tkv)) != TK_RIGHTBKT) {
uint_t filter = 0;
if (tok != TK_STRING) {
if (tok == TK_ERROR) {
mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSYM_2));
return (FALSE);
}
mv.mv_errcnt++;
continue;
}
(void) memset(&ms, 0, sizeof (ms));
ms.ms_name = tkv.tkv_str;
tok = ld_map_gettoken(mf, 0, &tkv);
if (tok == TK_ERROR) {
mv.mv_errcnt++;
continue;
}
mv.mv_vdp->vd_flags &= ~VER_FLG_WEAK;
switch (tok) {
case TK_COLON:
ld_map_sym_scope(mf, ms.ms_name, &mv);
continue;
case TK_EQUAL:
while ((tok = ld_map_gettoken(mf, 0, &tkv)) !=
TK_SEMICOLON) {
if (tok == TK_ERROR)
return (FALSE);
if (tok != TK_STRING) {
mf_fatal0(mf,
MSG_INTL(MSG_MAP_MALFORM));
return (FALSE);
}
if (filter) {
ld_map_sym_filtee(mf, &mv, &ms,
filter, tkv.tkv_str);
filter = 0;
continue;
}
ld_map_lowercase(tkv.tkv_str);
if (tkv.tkv_str[0] == 'v' ||
tkv.tkv_str[0] == 's') {
Xword number;
if (!valuetoxword(mf, &tkv, &number)) {
mv.mv_errcnt++;
return (FALSE);
}
switch (*tkv.tkv_str) {
case 'v':
if (ms.ms_value) {
mf_fatal(mf,
MSG_INTL(MSG_MAP_MOREONCE),
MSG_INTL(MSG_MAP_SYMVAL));
mv.mv_errcnt++;
continue;
}
ms.ms_value = (Addr)number;
ms.ms_value_set = TRUE;
break;
case 's':
if (ms.ms_size) {
mf_fatal(mf,
MSG_INTL(MSG_MAP_MOREONCE),
MSG_INTL(MSG_MAP_SYMSIZE));
mv.mv_errcnt++;
continue;
}
ms.ms_size = (Addr)number;
ms.ms_size_set = TRUE;
break;
}
} else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_MAP_FUNCTION)) == 0) {
ms.ms_shndx = SHN_ABS;
ms.ms_sdflags |= FLG_SY_SPECSEC;
ms.ms_type = STT_FUNC;
} else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_MAP_DATA)) == 0) {
ms.ms_shndx = SHN_ABS;
ms.ms_sdflags |= FLG_SY_SPECSEC;
ms.ms_type = STT_OBJECT;
} else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_MAP_COMMON)) == 0) {
ms.ms_shndx = SHN_COMMON;
ms.ms_sdflags |= FLG_SY_SPECSEC;
ms.ms_type = STT_OBJECT;
} else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_MAP_PARENT)) == 0) {
ms.ms_sdflags |= FLG_SY_PARENT;
ofl->ofl_flags |= FLG_OF_SYMINFO;
} else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_MAP_EXTERN)) == 0) {
ms.ms_sdflags |= FLG_SY_EXTERN;
ofl->ofl_flags |= FLG_OF_SYMINFO;
} else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_MAP_DIRECT)) == 0) {
ms.ms_sdflags |= FLG_SY_DIR;
ofl->ofl_flags |= FLG_OF_SYMINFO;
} else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_MAP_NODIRECT)) == 0) {
ms.ms_sdflags |= FLG_SY_NDIR;
ofl->ofl_flags |= FLG_OF_SYMINFO;
ofl->ofl_flags1 |=
(FLG_OF1_NDIRECT | FLG_OF1_NGLBDIR);
} else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_MAP_FILTER)) == 0) {
filter = FLG_SY_STDFLTR;
continue;
} else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_MAP_AUXILIARY)) == 0) {
filter = FLG_SY_AUXFLTR;
continue;
} else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_MAP_INTERPOSE)) == 0) {
if (!(ofl->ofl_flags & FLG_OF_EXEC)) {
mf_fatal0(mf,
MSG_INTL(MSG_MAP_NOINTPOSE));
mv.mv_errcnt++;
break;
}
ms.ms_sdflags |= FLG_SY_INTPOSE;
ofl->ofl_flags |= FLG_OF_SYMINFO;
ofl->ofl_dtflags_1 |= DF_1_SYMINTPOSE;
continue;
} else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_MAP_DYNSORT)) == 0) {
ms.ms_sdflags |= FLG_SY_DYNSORT;
ms.ms_sdflags &= ~FLG_SY_NODYNSORT;
continue;
} else if (strcmp(tkv.tkv_str,
MSG_ORIG(MSG_MAP_NODYNSORT)) == 0) {
ms.ms_sdflags &= ~FLG_SY_DYNSORT;
ms.ms_sdflags |= FLG_SY_NODYNSORT;
continue;
} else {
mf_fatal(mf,
MSG_INTL(MSG_MAP_UNKSYMDEF),
tkv.tkv_str);
mv.mv_errcnt++;
continue;
}
}
case TK_SEMICOLON:
if (*ms.ms_name == '*') {
ld_map_sym_autoreduce(mf, &mv);
continue;
}
if (filter && (ms.ms_filtee == NULL)) {
mf_fatal(mf, MSG_INTL(MSG_MAP_NOFILTER),
ms.ms_name);
mv.mv_errcnt++;
continue;
}
if (!ld_map_sym_enter(mf, &mv, &ms, NULL))
return (FALSE);
break;
default:
mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSCOL));
mv.mv_errcnt++;
continue;
}
}
if (mv.mv_errcnt)
return (FALSE);
if (!ld_map_sym_ver_fini(mf, &mv))
return (FALSE);
return (TRUE);
}
Boolean
ld_map_parse_v1(Mapfile *mf)
{
Sg_desc *sgp1;
Ent_desc *enp;
Token tok;
Boolean new_segment;
char *name;
Ofl_desc *ofl = mf->mf_ofl;
ld_map_tkval_t tkv;
avl_index_t where;
while ((tok = ld_map_gettoken(mf, TK_F_EOFOK, &tkv)) != TK_EOF) {
Xword ndx;
if (tok == TK_LEFTBKT) {
if (!map_version(mf, NULL))
return (FALSE);
continue;
}
if (tok != TK_STRING) {
if (tok != TK_ERROR)
mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPSEGNAM));
return (FALSE);
}
name = tkv.tkv_str;
tok = ld_map_gettoken(mf, 0, &tkv);
if (tok == TK_ERROR)
return (FALSE);
if (tok == TK_DASH) {
if (!map_dash(mf, name))
return (FALSE);
continue;
}
if (tok == TK_LEFTBKT) {
if (!map_version(mf, name))
return (FALSE);
continue;
}
sgp1 = ld_seg_lookup(mf->mf_ofl, name, &where);
new_segment = sgp1 == NULL;
if (!new_segment)
sgp1->sg_flags &= ~FLG_SG_DISABLED;
if (tok == TK_PIPE) {
if (sgp1 == NULL) {
mf_fatal(mf, MSG_INTL(MSG_MAP_SECINSEG),
name);
return (FALSE);
}
if (!map_pipe(mf, sgp1))
return (FALSE);
continue;
}
if (new_segment &&
((sgp1 = ld_map_seg_alloc(name, PT_NULL, 0)) == NULL))
return (FALSE);
switch (tok) {
case TK_EQUAL:
if (strcmp(sgp1->sg_name,
MSG_ORIG(MSG_STR_HWCAP_1)) == 0) {
if (!map_cap(mf, CA_SUNW_HW_1,
&ofl->ofl_ocapset.oc_hw_1))
return (FALSE);
continue;
}
if (strcmp(sgp1->sg_name,
MSG_ORIG(MSG_STR_SFCAP_1)) == 0) {
if (!map_cap(mf, CA_SUNW_SF_1,
&ofl->ofl_ocapset.oc_sf_1))
return (FALSE);
continue;
}
if (!new_segment && DBG_ENABLED) {
ndx = ld_map_seg_index(mf, sgp1);
Dbg_map_seg(ofl, DBG_STATE_MOD_BEFORE,
ndx, sgp1, mf->mf_lineno);
}
if (!map_equal(mf, sgp1))
return (FALSE);
if (sgp1->sg_phdr.p_type == PT_SUNWSTACK) {
Sg_desc *stack = ld_map_seg_stack(mf);
if (sgp1->sg_flags & FLG_SG_P_FLAGS)
stack->sg_phdr.p_flags =
sgp1->sg_phdr.p_flags;
DBG_CALL(Dbg_map_seg(ofl,
DBG_STATE_MOD_AFTER, ndx, sgp1,
mf->mf_lineno));
free(sgp1);
break;
}
if (new_segment) {
switch (ld_map_seg_insert(mf, DBG_STATE_NEW,
sgp1, where)) {
case SEG_INS_SKIP:
continue;
case SEG_INS_FAIL:
return (FALSE);
}
} else {
DBG_CALL(Dbg_map_seg(ofl,
DBG_STATE_MOD_AFTER, ndx, sgp1,
mf->mf_lineno));
}
break;
case TK_COLON:
if (new_segment) {
switch (ld_map_seg_insert(mf,
DBG_STATE_NEW_IMPLICIT, sgp1, where)) {
case SEG_INS_SKIP:
continue;
case SEG_INS_FAIL:
return (FALSE);
}
} else if (sgp1->sg_flags & FLG_SG_EMPTY) {
mf_fatal0(mf, MSG_INTL(MSG_MAP_SEGEMPSEC));
return (FALSE);
}
enp = ld_map_seg_ent_add(mf, sgp1, NULL);
if ((enp == NULL) || !map_colon(mf, enp))
return (FALSE);
DBG_CALL(Dbg_map_ent(ofl->ofl_lml, enp, ofl,
mf->mf_lineno));
break;
case TK_ATSIGN:
if (new_segment) {
switch (ld_map_seg_insert(mf,
DBG_STATE_NEW_IMPLICIT, sgp1, where)) {
case SEG_INS_SKIP:
continue;
case SEG_INS_FAIL:
return (FALSE);
}
}
if (!map_atsign(mf, sgp1))
return (FALSE);
break;
case TK_ERROR:
return (FALSE);
default:
mf_fatal0(mf, MSG_INTL(MSG_MAP_EXPEQU));
return (FALSE);
}
}
return (TRUE);
}