summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorrie <none@none>2007-05-03 11:50:51 -0700
committerrie <none@none>2007-05-03 11:50:51 -0700
commit7a3a47260649c4f8a454301b45ae5e66360ed7a6 (patch)
tree2503ba4c77d9e285c15dc96e3655f07ee126936b /usr/src
parent2eec250a857894111b43b783c72c0197898c34af (diff)
downloadillumos-gate-7a3a47260649c4f8a454301b45ae5e66360ed7a6.tar.gz
5006034 need ?E mapfile feature extension
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/sgs/libld/common/entry.c11
-rw-r--r--usr/src/cmd/sgs/libld/common/libld.msg12
-rw-r--r--usr/src/cmd/sgs/libld/common/map.c173
-rw-r--r--usr/src/cmd/sgs/libld/common/outfile.c10
-rw-r--r--usr/src/cmd/sgs/packages/common/SUNWonld-README1
5 files changed, 123 insertions, 84 deletions
diff --git a/usr/src/cmd/sgs/libld/common/entry.c b/usr/src/cmd/sgs/libld/common/entry.c
index eb436c6b56..124d9c30b9 100644
--- a/usr/src/cmd/sgs/libld/common/entry.c
+++ b/usr/src/cmd/sgs/libld/common/entry.c
@@ -182,10 +182,10 @@ static const Ent_desc ent_desc[] = {
* the output file descriptor.
*/
uintptr_t
-ld_ent_setup(Ofl_desc * ofl, Xword segalign)
+ld_ent_setup(Ofl_desc *ofl, Xword segalign)
{
- Ent_desc * enp;
- Sg_desc * sgp;
+ Ent_desc *enp;
+ Sg_desc *sgp;
size_t size;
/*
@@ -204,7 +204,7 @@ ld_ent_setup(Ofl_desc * ofl, Xword segalign)
SGSOFFSETOF(Sym_avlnode, sav_node));
/*
- * The datasegment permissions can differ depending on whether
+ * The data segment permissions can differ depending on whether
* this object is built statically or dynamically.
*/
if (ofl->ofl_flags & FLG_OF_DYNAMIC) {
@@ -244,8 +244,7 @@ ld_ent_setup(Ofl_desc * ofl, Xword segalign)
* a default alignment (ld(1) and ld.so.1 initialize this differently).
*/
for (size = 0; size < sizeof (sg_desc); size += sizeof (Sg_desc)) {
-
- Phdr * phdr = &(sgp->sg_phdr);
+ Phdr *phdr = &(sgp->sg_phdr);
if ((list_appendc(&ofl->ofl_segs, sgp)) == 0)
return (S_ERROR);
diff --git a/usr/src/cmd/sgs/libld/common/libld.msg b/usr/src/cmd/sgs/libld/common/libld.msg
index 2b51f4fe86..55608f6118 100644
--- a/usr/src/cmd/sgs/libld/common/libld.msg
+++ b/usr/src/cmd/sgs/libld/common/libld.msg
@@ -870,10 +870,13 @@
@ MSG_MAP_UNEXDEP "%s: %lld: dependency `%s' unexpected; ignored"
@ MSG_MAP_UNEXTOK "%s: %lld: unexpected occurrence of `%c' token"
-@ MSG_MAP_SEGEMPEXE "%s: %lld: empty segment definition for this output \
- file is unsupported"
-@ MSG_MAP_SEGEMPLOAD "%s: %lld: empty segment must be of type LOAD"
-@ MSG_MAP_SEGEMPATT "%s: %lld: empty segment must have an address and size"
+@ MSG_MAP_SEGEMPLOAD "%s: %lld: empty segment must be of type LOAD or NULL"
+@ MSG_MAP_SEGEMPEXE "%s: %lld: a LOAD empty segment definition is only \
+ allowed when creating a dynamic executable"
+@ MSG_MAP_SEGEMPATT "%s: %lld: a LOAD empty segment must have an address \
+ and size"
+@ MSG_MAP_SEGEMPNOATT "%s: %lld: a NULL empty segment must not have an address \
+ or size"
@ MSG_MAP_SEGEMPSEC "%s: %lld: empty segment can not have sections \
assigned to it"
@ MSG_MAP_SEGEMNOPERM "%s: %lld: empty segment must not have \
@@ -1136,6 +1139,7 @@
@ MSG_MAP_TOK_2 " \"\t\n:;=#"
@ MSG_MAP_LOAD "load"
@ MSG_MAP_NOTE "note"
+@ MSG_MAP_NULL "null"
@ MSG_MAP_STACK "stack"
@ MSG_MAP_NEED "need"
@ MSG_MAP_SPECVERS "specvers"
diff --git a/usr/src/cmd/sgs/libld/common/map.c b/usr/src/cmd/sgs/libld/common/map.c
index 3a138b2aea..e54d7c6f1d 100644
--- a/usr/src/cmd/sgs/libld/common/map.c
+++ b/usr/src/cmd/sgs/libld/common/map.c
@@ -325,6 +325,26 @@ map_cap(const char *mapfile, Word type, Ofl_desc *ofl)
}
/*
+ * Common segment error checking.
+ */
+static Boolean
+seg_check(const char *mapfile, Sg_desc *sgp, Ofl_desc *ofl, Boolean b_type,
+ Word p_type)
+{
+ if (b_type) {
+ eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_MAP_MOREONCE),
+ mapfile, EC_XWORD(Line_num), MSG_INTL(MSG_MAP_SEGTYP));
+ return (FALSE);
+ }
+ if ((sgp->sg_flags & FLG_SG_TYPE) && (sgp->sg_phdr.p_type != p_type)) {
+ eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_MAP_REDEFATT),
+ mapfile, EC_XWORD(Line_num), MSG_INTL(MSG_MAP_SEGTYP),
+ sgp->sg_name);
+ }
+ return (TRUE);
+}
+
+/*
* Process a mapfile segment declaration definition.
* segment_name = segment_attribute;
* segment_attribute : segment_type segment_flags virtual_addr
@@ -362,58 +382,43 @@ map_equal(const char *mapfile, Sg_desc *sgp, Ofl_desc *ofl)
lowercase(Start_tok);
/*
- * Segment type. Presently there can only be multiple
- * PT_LOAD and PT_NOTE segments, other segment types are
- * only defined in seg_desc[].
+ * Segment type. Users are permitted to define PT_LOAD,
+ * PT_NOTE, PT_STACK and PT_NULL segments. Other segment types
+ * are only defined in seg_desc[].
*/
if (strcmp(Start_tok, MSG_ORIG(MSG_MAP_LOAD)) == 0) {
- if (b_type) {
- eprintf(ofl->ofl_lml, ERR_FATAL,
- MSG_INTL(MSG_MAP_MOREONCE), mapfile,
- EC_XWORD(Line_num),
- MSG_INTL(MSG_MAP_SEGTYP));
+ if ((b_type = seg_check(mapfile, sgp, ofl, b_type,
+ PT_LOAD)) == FALSE)
return (S_ERROR);
- }
- if ((sgp->sg_flags & FLG_SG_TYPE) &&
- (sgp->sg_phdr.p_type != PT_LOAD))
- eprintf(ofl->ofl_lml, ERR_WARNING,
- MSG_INTL(MSG_MAP_REDEFATT), mapfile,
- EC_XWORD(Line_num),
- MSG_INTL(MSG_MAP_SEGTYP), sgp->sg_name);
+
sgp->sg_phdr.p_type = PT_LOAD;
sgp->sg_flags |= FLG_SG_TYPE;
- b_type = TRUE;
+
} else if (strcmp(Start_tok, MSG_ORIG(MSG_MAP_STACK)) == 0) {
- if (b_type) {
- eprintf(ofl->ofl_lml, ERR_FATAL,
- MSG_INTL(MSG_MAP_MOREONCE), mapfile,
- EC_XWORD(Line_num),
- MSG_INTL(MSG_MAP_SEGTYP));
+ if ((b_type = seg_check(mapfile, sgp, ofl, b_type,
+ PT_SUNWSTACK)) == FALSE)
return (S_ERROR);
- }
+
sgp->sg_phdr.p_type = PT_SUNWSTACK;
- sgp->sg_flags |= (FLG_SG_TYPE|FLG_SG_EMPTY);
- b_type = TRUE;
+ sgp->sg_flags |= (FLG_SG_TYPE | FLG_SG_EMPTY);
+
+ } else if (strcmp(Start_tok, MSG_ORIG(MSG_MAP_NULL)) == 0) {
+ if ((b_type = seg_check(mapfile, sgp, ofl, b_type,
+ PT_NULL)) == FALSE)
+ return (S_ERROR);
+
+ sgp->sg_phdr.p_type = PT_NULL;
+ sgp->sg_flags |= FLG_SG_TYPE;
+
} else if (strcmp(Start_tok, MSG_ORIG(MSG_MAP_NOTE)) == 0) {
- if (b_type) {
- eprintf(ofl->ofl_lml, ERR_FATAL,
- MSG_INTL(MSG_MAP_MOREONCE), mapfile,
- EC_XWORD(Line_num),
- MSG_INTL(MSG_MAP_SEGTYP));
+ if ((b_type = seg_check(mapfile, sgp, ofl, b_type,
+ PT_NOTE)) == FALSE)
return (S_ERROR);
- }
- if ((sgp->sg_flags & FLG_SG_TYPE) &&
- (sgp->sg_phdr.p_type != PT_NOTE))
- eprintf(ofl->ofl_lml, ERR_WARNING,
- MSG_INTL(MSG_MAP_REDEFATT), mapfile,
- EC_XWORD(Line_num),
- MSG_INTL(MSG_MAP_SEGTYP), sgp->sg_name);
+
sgp->sg_phdr.p_type = PT_NOTE;
sgp->sg_flags |= FLG_SG_TYPE;
- b_type = TRUE;
}
-
/* Segment Flags. */
else if (*Start_tok == '?') {
@@ -621,34 +626,56 @@ map_equal(const char *mapfile, Sg_desc *sgp, Ofl_desc *ofl)
}
/*
- * Segment reservations are only allowable for executables. In addition
- * they must have an associated address, size, no permisions,
- * and are only meaningful for LOAD segments (the last failure
- * we can correct, hence the warning condition).
+ * Empty segments can be used to define PT_LOAD segment reservations, or
+ * to reserve PT_NULL program headers.
+ *
+ * PT_LOAD reservations are only allowed within executables, as the
+ * reservation must be established through exec() as part of initial
+ * process loading. In addition, PT_LOAD reservations must have an
+ * associated address and size.
+ *
+ * PT_NULL program headers are established for later use by applications
+ * such as the post-optimizer. PT_NULL headers should have no other
+ * attributes assigned.
*/
if ((sgp->sg_flags & FLG_SG_EMPTY) &&
(sgp->sg_phdr.p_type != PT_SUNWSTACK)) {
- if (!(ofl->ofl_flags & FLG_OF_EXEC)) {
- eprintf(ofl->ofl_lml, ERR_FATAL,
- MSG_INTL(MSG_MAP_SEGEMPEXE), mapfile,
- EC_XWORD(Line_num));
- return (S_ERROR);
- }
+
+ /*
+ * Any style of empty segment should have no permissions.
+ */
if (sgp->sg_phdr.p_flags != 0) {
eprintf(ofl->ofl_lml, ERR_FATAL,
MSG_INTL(MSG_MAP_SEGEMNOPERM), mapfile,
EC_XWORD(Line_num),
- EC_WORD(sgp->sg_phdr.p_flags));
- return (S_ERROR);
- }
- if ((sgp->sg_flags & (FLG_SG_LENGTH | FLG_SG_VADDR)) !=
- (FLG_SG_LENGTH | FLG_SG_VADDR)) {
- eprintf(ofl->ofl_lml, ERR_FATAL,
- MSG_INTL(MSG_MAP_SEGEMPATT), mapfile,
- EC_XWORD(Line_num));
+ EC_WORD(sgp->sg_phdr.p_flags));
return (S_ERROR);
}
- if (sgp->sg_phdr.p_type != PT_LOAD) {
+
+ if (sgp->sg_phdr.p_type == PT_LOAD) {
+ if ((ofl->ofl_flags & FLG_OF_EXEC) == 0) {
+ eprintf(ofl->ofl_lml, ERR_FATAL,
+ MSG_INTL(MSG_MAP_SEGEMPEXE), mapfile,
+ EC_XWORD(Line_num));
+ return (S_ERROR);
+ }
+ if ((sgp->sg_flags & (FLG_SG_LENGTH | FLG_SG_VADDR)) !=
+ (FLG_SG_LENGTH | FLG_SG_VADDR)) {
+ eprintf(ofl->ofl_lml, ERR_FATAL,
+ MSG_INTL(MSG_MAP_SEGEMPATT), mapfile,
+ EC_XWORD(Line_num));
+ return (S_ERROR);
+ }
+ } else if (sgp->sg_phdr.p_type == PT_NULL) {
+ if ((sgp->sg_flags & (FLG_SG_LENGTH | FLG_SG_VADDR)) &&
+ ((sgp->sg_length != 0) ||
+ (sgp->sg_phdr.p_vaddr != 0))) {
+ eprintf(ofl->ofl_lml, ERR_FATAL,
+ MSG_INTL(MSG_MAP_SEGEMPNOATT), mapfile,
+ EC_XWORD(Line_num));
+ return (S_ERROR);
+ }
+ } else {
eprintf(ofl->ofl_lml, ERR_WARNING,
MSG_INTL(MSG_MAP_SEGEMPLOAD), mapfile,
EC_XWORD(Line_num));
@@ -664,8 +691,9 @@ map_equal(const char *mapfile, Sg_desc *sgp, Ofl_desc *ofl)
* When clearing an attribute leave the flag set as an indicator for
* later entries re-specifying the same segment.
*/
- 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_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);
@@ -2003,15 +2031,19 @@ ld_sort_seg_list(Ofl_desc *ofl)
seg1.head = seg1.tail = seg2.head = seg2.tail = NULL;
/*
- * Add the .phdr and .interp segments to our list. These segments must
- * occur before any PT_LOAD segments (refer exec/elf/elf.c).
+ * Add the .phdr and .interp segments to our list. These segments must
+ * occur before any PT_LOAD segments (refer exec/elf/elf.c). Also add
+ * the capabilities segment. This isn't essential, but the capabilities
+ * section is one of the first in an object.
*/
for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) {
Word type = sgp1->sg_phdr.p_type;
- if ((type == PT_PHDR) || (type == PT_INTERP))
+ if ((type == PT_PHDR) || (type == PT_INTERP) ||
+ (type == PT_SUNWCAP)) {
if (list_appendc(&seg1, sgp1) == 0)
return (S_ERROR);
+ }
}
/*
@@ -2019,8 +2051,10 @@ ld_sort_seg_list(Ofl_desc *ofl)
*/
for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) {
DBG_CALL(Dbg_map_sort_orig(ofl->ofl_lml, sgp1));
+
if (sgp1->sg_phdr.p_type != PT_LOAD)
continue;
+
if (!(sgp1->sg_flags & FLG_SG_VADDR) ||
(sgp1->sg_flags & FLG_SG_EMPTY)) {
if (list_appendc(&seg2, sgp1) == 0)
@@ -2077,7 +2111,7 @@ ld_sort_seg_list(Ofl_desc *ofl)
}
/*
- * add the sorted loadable segments to our list
+ * Add the sorted loadable segments to our list.
*/
for (LIST_TRAVERSE(&seg2, lnp1, sgp1)) {
if (list_appendc(&seg1, sgp1) == 0)
@@ -2085,15 +2119,16 @@ ld_sort_seg_list(Ofl_desc *ofl)
}
/*
- * add all other segments to our list
+ * Add all other segments to our list.
*/
for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp1)) {
Word type = sgp1->sg_phdr.p_type;
if ((type != PT_PHDR) && (type != PT_INTERP) &&
- (type != PT_LOAD))
+ (type != PT_SUNWCAP) && (type != PT_LOAD)) {
if (list_appendc(&seg1, sgp1) == 0)
return (S_ERROR);
+ }
}
ofl->ofl_segs.head = ofl->ofl_segs.tail = NULL;
@@ -2109,8 +2144,6 @@ ld_sort_seg_list(Ofl_desc *ofl)
return (1);
}
-
-
/*
* Parse the mapfile.
*/
@@ -2324,6 +2357,7 @@ ld_map_parse(const char *mapfile, Ofl_desc *ofl)
return (S_ERROR);
DBG_CALL(Dbg_cap_mapfile(ofl->ofl_lml,
CA_SUNW_HW_1, ofl->ofl_hwcap_1, M_MACH));
+ continue;
} else if (strcmp(sgp1->sg_name,
MSG_ORIG(MSG_STR_SFCAP_1)) == 0) {
@@ -2332,6 +2366,7 @@ ld_map_parse(const char *mapfile, Ofl_desc *ofl)
return (S_ERROR);
DBG_CALL(Dbg_cap_mapfile(ofl->ofl_lml,
CA_SUNW_SF_1, ofl->ofl_sfcap_1, M_MACH));
+ continue;
} else {
if (map_equal(mapfile, sgp1, ofl) == S_ERROR)
@@ -2401,7 +2436,8 @@ ld_map_parse(const char *mapfile, Ofl_desc *ofl)
* If specific fields have not been supplied via
* map_equal(), make sure defaults are supplied.
*/
- if (sgp1->sg_phdr.p_type == PT_NULL) {
+ if (((sgp1->sg_flags & FLG_SG_TYPE) == 0) &&
+ (sgp1->sg_phdr.p_type == PT_NULL)) {
sgp1->sg_phdr.p_type = PT_LOAD;
sgp1->sg_flags |= FLG_SG_TYPE;
}
@@ -2420,6 +2456,7 @@ ld_map_parse(const char *mapfile, Ofl_desc *ofl)
*/
switch (sgp1->sg_phdr.p_type) {
case PT_LOAD:
+ case PT_NULL:
if (sgp1->sg_flags & FLG_SG_EMPTY)
src_type = 4;
else
diff --git a/usr/src/cmd/sgs/libld/common/outfile.c b/usr/src/cmd/sgs/libld/common/outfile.c
index 8d42c79d06..9332de698c 100644
--- a/usr/src/cmd/sgs/libld/common/outfile.c
+++ b/usr/src/cmd/sgs/libld/common/outfile.c
@@ -464,18 +464,16 @@ ld_create_outfile(Ofl_desc *ofl)
} else if (ptype == PT_SUNWBSS) {
if (ofl->ofl_issunwbss)
nseg++;
- } else if (ptype == PT_SUNWSTACK) {
- nseg++;
} else if (ptype == PT_SUNWDTRACE) {
if (ofl->ofl_dtracesym)
nseg++;
} else if (ptype == PT_SUNWCAP) {
if (ofl->ofl_oscap)
nseg++;
- } else if ((sgp->sg_osdescs != NULL) ||
- (sgp->sg_flags & FLG_SG_EMPTY)) {
- if (((sgp->sg_flags & FLG_SG_EMPTY) == 0) &&
- ((sgp->sg_flags & FLG_SG_PHREQ) == 0)) {
+ } else if (sgp->sg_flags & FLG_SG_EMPTY) {
+ nseg++;
+ } else if (sgp->sg_osdescs != NULL) {
+ if ((sgp->sg_flags & FLG_SG_PHREQ) == 0) {
/*
* If this is a segment for which
* we are not making a program header,
diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README
index 66c15b0ba2..9fae7f8309 100644
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README
+++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README
@@ -1232,3 +1232,4 @@ Bugid Risk Synopsis
6341667 elfdump should check alignments of ELF header elements
6387860 elfdump cores, when processing linux built ELF file
6198202 mcs -d dumps core
+5006034 need ?E mapfile feature extension (D)