tech-toolchain archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Linking C++



Kamil Rytarowski <n54%gmx.com@localhost> wrote:
>On 24.10.2019 01:20, Robert Swindells wrote:
>> 
>> Kamil Rytarowski <n54%gmx.com@localhost> wrote:
>>> On 23.10.2019 19:28, Robert Swindells wrote:
>>>>
>>>> There is a restriction in our ld.elf_so that it can only load two
>>>> segments.
>>>
>>> Please test the patch from:
>>>
>>> http://mail-index.netbsd.org/tech-toolchain/2019/01/06/msg003368.html
>> 
>> The patch works for me.
>> 
>> Would something like this get into NetBSD-9 ?
> 
>Unless we will get a patch with a better version, I plan to land it
>after 2 weeks and pull-request to -9.
>
>BTW. Please share your rebased version.

Patch attached. It hasn't really changed, just the context around one
of the chunks.

Index: map_object.c
===================================================================
RCS file: /cvsroot/src/libexec/ld.elf_so/map_object.c,v
retrieving revision 1.60
diff -u -r1.60 map_object.c
--- map_object.c	6 Jan 2019 19:44:54 -0000	1.60
+++ map_object.c	24 Oct 2019 10:35:52 -0000
@@ -71,7 +71,7 @@
 #endif
 	size_t		 phsize;
 	Elf_Phdr	*phlimit;
-	Elf_Phdr	*segs[2];
+	Elf_Phdr	*segs[3];
 	int		 nsegs;
 	caddr_t		 mapbase = MAP_FAILED;
 	size_t		 mapsize = 0;
@@ -80,8 +80,6 @@
 	Elf_Addr	 base_alignment;
 	Elf_Addr	 base_vaddr;
 	Elf_Addr	 base_vlimit;
-	Elf_Addr	 text_vlimit;
-	int		 text_flags;
 	void		*base_addr;
 	Elf_Off		 data_offset;
 	Elf_Addr	 data_vaddr;
@@ -93,14 +91,19 @@
 #endif
 	Elf_Addr	 phdr_vaddr;
 	size_t		 phdr_memsz;
+#if 0
 	caddr_t		 gap_addr;
 	size_t		 gap_size;
+#endif
 	int i;
 #ifdef RTLD_LOADER
 	Elf_Addr	 clear_vaddr;
 	caddr_t		 clear_addr;
 	size_t		 nclear;
 #endif
+	Elf_Addr	 bss_vaddr;
+	caddr_t		 bss_addr;
+	Elf_Addr	 bss_vlimit;
 #ifdef GNU_RELRO
 	Elf_Addr 	 relro_page;
 	size_t		 relro_size;
@@ -191,7 +194,7 @@
 			break;
 
 		case PT_LOAD:
-			if (nsegs < 2)
+			if (nsegs < 3)
 				segs[nsegs] = phdr;
 			++nsegs;
 
@@ -242,7 +245,7 @@
 		_rtld_error("%s: not dynamically linked", path);
 		goto bad;
 	}
-	if (nsegs != 2) {
+	if (nsegs < 0 || nsegs > 3) {
 		_rtld_error("%s: wrong number of segments (%d != 2)", path,
 		    nsegs);
 		goto bad;
@@ -263,18 +266,8 @@
 	base_alignment = segs[0]->p_align;
 	base_offset = round_down(segs[0]->p_offset);
 	base_vaddr = round_down(segs[0]->p_vaddr);
-	base_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_memsz);
-	text_vlimit = round_up(segs[0]->p_vaddr + segs[0]->p_memsz);
-	text_flags = protflags(segs[0]->p_flags);
-	data_offset = round_down(segs[1]->p_offset);
-	data_vaddr = round_down(segs[1]->p_vaddr);
-	data_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_filesz);
-	data_flags = protflags(segs[1]->p_flags);
-#ifdef RTLD_LOADER
-	clear_vaddr = segs[1]->p_vaddr + segs[1]->p_filesz;
-#endif
+	base_vlimit = round_up(segs[nsegs-1]->p_vaddr + segs[nsegs-1]->p_memsz);
 
-	obj->textsize = text_vlimit - base_vaddr;
 	obj->vaddrbase = base_vaddr;
 	obj->isdynamic = ehdr->e_type == ET_DYN;
 
@@ -322,11 +315,13 @@
 	dbg(("%s: phdr %p phsize %zu (%s)", obj->path, obj->phdr, obj->phsize,
 	     obj->phdr_loaded ? "loaded" : "allocated"));
 
+#if 0 /* TODO? */
 	/* Unmap header if it overlaps the first load section. */
 	if (base_offset < _rtld_pagesz) {
 		munmap(ehdr, _rtld_pagesz);
 		obj->ehdr = MAP_FAILED;
 	}
+#endif
 
 	/*
 	 * Calculate log2 of the base section alignment.
@@ -347,7 +342,7 @@
 	}
 #endif
 	mapsize = base_vlimit - base_vaddr;
-	mapbase = mmap(base_addr, mapsize, text_flags,
+	mapbase = mmap(base_addr, mapsize, PROT_NONE, // was: text_flags,
 	    mapflags | MAP_FILE | MAP_PRIVATE, fd, base_offset);
 	if (mapbase == MAP_FAILED) {
 		_rtld_error("mmap of entire address space failed: %s",
@@ -361,23 +356,51 @@
 	}
 #endif
 
-	/* Overlay the data segment onto the proper region. */
-	data_addr = mapbase + (data_vaddr - base_vaddr);
-	if (mmap(data_addr, data_vlimit - data_vaddr, data_flags,
-	    MAP_FILE | MAP_PRIVATE | MAP_FIXED, fd, data_offset) ==
-	    MAP_FAILED) {
-		_rtld_error("mmap of data failed: %s", xstrerror(errno));
-		goto bad;
-	}
+	/* Overlay the individual segments onto the proper regions. */
+	for (i = 0; i < nsegs; i++) {
+		data_offset = round_down(segs[i]->p_offset);
+		data_vaddr = round_down(segs[i]->p_vaddr);
+		data_vlimit = round_up(segs[i]->p_vaddr + segs[i]->p_filesz);
+		data_flags = protflags(segs[i]->p_flags);
+
+		data_addr = mapbase + (data_vaddr - base_vaddr);
+		if (data_flags & PF_X) { /* text segment */
+			obj->textsize = data_vlimit - data_vaddr;
+		}
 
-	/* Overlay the bss segment onto the proper region. */
-	if (mmap(mapbase + data_vlimit - base_vaddr, base_vlimit - data_vlimit,
-	    data_flags, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) ==
-	    MAP_FAILED) {
-		_rtld_error("mmap of bss failed: %s", xstrerror(errno));
-		goto bad;
+		if (mmap(data_addr, data_vlimit - data_vaddr, data_flags,
+			MAP_FILE | MAP_PRIVATE | MAP_FIXED, fd, data_offset) ==
+			MAP_FAILED) {
+			_rtld_error("mmap of data failed: %s", xstrerror(errno));
+			goto bad;
+		}
+
+		if (segs[i]->p_filesz != segs[i]->p_memsz) {
+#ifdef RTLD_LOADER
+			clear_vaddr = segs[i]->p_vaddr + segs[i]->p_filesz;
+
+			/* Clear any BSS in the last page of the data segment. */
+			clear_addr = mapbase + (clear_vaddr - base_vaddr);
+			if ((nclear = data_vlimit - clear_vaddr) > 0)
+				memset(clear_addr, 0, nclear);
+#endif
+
+			/* Overlay the bss segment onto the proper region. */
+			bss_vaddr = data_vlimit;
+			bss_addr = mapbase + (bss_vaddr - base_vaddr);
+			bss_vlimit = round_up(segs[i]->p_vaddr + segs[i]->p_memsz);
+			if (bss_vlimit > bss_vaddr) {
+				if (mmap(bss_addr, bss_vlimit - bss_vaddr, data_flags,
+					MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) ==
+					MAP_FAILED) {
+					_rtld_error("mmap of bss failed: %s", xstrerror(errno));
+					goto bad;
+				}
+			}
+		}
 	}
 
+#if 0 /* TODO */
 	/* Unmap the gap between the text and data. */
 	gap_addr = mapbase + round_up(text_vlimit - base_vaddr);
 	gap_size = data_addr - gap_addr;
@@ -386,14 +409,6 @@
 		    xstrerror(errno));
 		goto bad;
 	}
-
-#ifdef RTLD_LOADER
-	/* Clear any BSS in the last page of the data segment. */
-	clear_addr = mapbase + (clear_vaddr - base_vaddr);
-	if ((nclear = data_vlimit - clear_vaddr) > 0)
-		memset(clear_addr, 0, nclear);
-
-	/* Non-file portion of BSS mapped above. */
 #endif
 
 #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)


Home | Main Index | Thread Index | Old Index