changeset 4157:2692c9055fcf

5006034 need ?E mapfile feature extension
author rie
date Thu, 03 May 2007 11:50:51 -0700
parents da0f64b64bfa
children 2c6eae4728c5
files usr/src/cmd/sgs/libld/common/entry.c usr/src/cmd/sgs/libld/common/libld.msg usr/src/cmd/sgs/libld/common/map.c usr/src/cmd/sgs/libld/common/outfile.c usr/src/cmd/sgs/packages/common/SUNWonld-README
diffstat 5 files changed, 123 insertions(+), 84 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/sgs/libld/common/entry.c	Thu May 03 09:59:24 2007 -0700
+++ b/usr/src/cmd/sgs/libld/common/entry.c	Thu May 03 11:50:51 2007 -0700
@@ -182,10 +182,10 @@
  * 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 @@
 	    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 @@
 	 * 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);
--- a/usr/src/cmd/sgs/libld/common/libld.msg	Thu May 03 09:59:24 2007 -0700
+++ b/usr/src/cmd/sgs/libld/common/libld.msg	Thu May 03 11:50:51 2007 -0700
@@ -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"
--- a/usr/src/cmd/sgs/libld/common/map.c	Thu May 03 09:59:24 2007 -0700
+++ b/usr/src/cmd/sgs/libld/common/map.c	Thu May 03 11:50:51 2007 -0700
@@ -325,6 +325,26 @@
 }
 
 /*
+ * 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 @@
 		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 @@
 	}
 
 	/*
-	 * 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));
+			    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));
-			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 @@
 	 * 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 @@
 	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 @@
 	 */
 	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 @@
 	}
 
 	/*
-	 * 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 @@
 	}
 
 	/*
-	 * 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 @@
 	return (1);
 }
 
-
-
 /*
  * Parse the mapfile.
  */
@@ -2324,6 +2357,7 @@
 					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 @@
 					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 @@
 			 * 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 @@
 			 */
 			switch (sgp1->sg_phdr.p_type) {
 			case PT_LOAD:
+			case PT_NULL:
 				if (sgp1->sg_flags & FLG_SG_EMPTY)
 					src_type = 4;
 				else
--- a/usr/src/cmd/sgs/libld/common/outfile.c	Thu May 03 09:59:24 2007 -0700
+++ b/usr/src/cmd/sgs/libld/common/outfile.c	Thu May 03 11:50:51 2007 -0700
@@ -464,18 +464,16 @@
 			} 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,
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README	Thu May 03 09:59:24 2007 -0700
+++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README	Thu May 03 11:50:51 2007 -0700
@@ -1232,3 +1232,4 @@
 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)