112611Sasmotrak/* $NetBSD: map_object.c,v 1.42 2011/03/09 23:10:07 joerg Exp $ */ 212611Sasmotrak 312611Sasmotrak/* 412611Sasmotrak * Copyright 1996 John D. Polstra. 512611Sasmotrak * Copyright 1996 Matt Thomas <matt@3am-software.com> 612611Sasmotrak * Copyright 2002 Charles M. Hannum <root@ihack.net> 712611Sasmotrak * All rights reserved. 812611Sasmotrak * 912611Sasmotrak * Redistribution and use in source and binary forms, with or without 1012611Sasmotrak * modification, are permitted provided that the following conditions 1112611Sasmotrak * are met: 1212611Sasmotrak * 1. Redistributions of source code must retain the above copyright 1312611Sasmotrak * notice, this list of conditions and the following disclaimer. 1412611Sasmotrak * 2. Redistributions in binary form must reproduce the above copyright 1512611Sasmotrak * notice, this list of conditions and the following disclaimer in the 1612611Sasmotrak * documentation and/or other materials provided with the distribution. 1712611Sasmotrak * 3. All advertising materials mentioning features or use of this software 1812611Sasmotrak * must display the following acknowledgement: 1912611Sasmotrak * This product includes software developed by John Polstra. 2012611Sasmotrak * 4. The name of the author may not be used to endorse or promote products 2112611Sasmotrak * derived from this software without specific prior written permission. 2212611Sasmotrak * 2312611Sasmotrak * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2412611Sasmotrak * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2512611Sasmotrak * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2612611Sasmotrak * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2712611Sasmotrak * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2812611Sasmotrak * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2912611Sasmotrak * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3012611Sasmotrak * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3112611Sasmotrak * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3212611Sasmotrak * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3312611Sasmotrak */ 3412611Sasmotrak 3512611Sasmotrak#include <sys/cdefs.h> 3612611Sasmotrak#ifndef lint 3712611Sasmotrak__RCSID("$NetBSD: map_object.c,v 1.42 2011/03/09 23:10:07 joerg Exp $"); 3812611Sasmotrak#endif /* not lint */ 3912611Sasmotrak 4012611Sasmotrak#include <errno.h> 4112611Sasmotrak#include <stddef.h> 4212611Sasmotrak#include <stdlib.h> 4312611Sasmotrak#include <string.h> 4412611Sasmotrak#include <unistd.h> 4512611Sasmotrak#include <sys/stat.h> 4612611Sasmotrak#include <sys/types.h> 4712611Sasmotrak#include <sys/mman.h> 4812611Sasmotrak 4912611Sasmotrak#include "debug.h" 5012611Sasmotrak#include "rtld.h" 5112611Sasmotrak 5212611Sasmotrakstatic int protflags(int); /* Elf flags -> mmap protection */ 5312611Sasmotrak 5412611Sasmotrak#define EA_UNDEF (~(Elf_Addr)0) 5512611Sasmotrak 5612611Sasmotrak/* 5712611Sasmotrak * Map a shared object into memory. The argument is a file descriptor, 5812611Sasmotrak * which must be open on the object and positioned at its beginning. 5912611Sasmotrak * 6012611Sasmotrak * The return value is a pointer to a newly-allocated Obj_Entry structure 6112611Sasmotrak * for the shared object. Returns NULL on failure. 6212611Sasmotrak */ 6312611SasmotrakObj_Entry * 6412611Sasmotrak_rtld_map_object(const char *path, int fd, const struct stat *sb) 6512611Sasmotrak{ 6612611Sasmotrak Obj_Entry *obj; 6712611Sasmotrak Elf_Ehdr *ehdr; 6812611Sasmotrak Elf_Phdr *phdr; 6912611Sasmotrak#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 7012611Sasmotrak Elf_Phdr *phtls; 7112611Sasmotrak#endif 7212611Sasmotrak size_t phsize; 7312611Sasmotrak Elf_Phdr *phlimit; 7412611Sasmotrak Elf_Phdr *segs[2]; 7512611Sasmotrak int nsegs; 7612611Sasmotrak caddr_t mapbase = MAP_FAILED; 7712611Sasmotrak size_t mapsize = 0; 7812611Sasmotrak int mapflags; 7912611Sasmotrak Elf_Off base_offset; 8012611Sasmotrak#ifdef MAP_ALIGNED 8112611Sasmotrak Elf_Addr base_alignment; 8212611Sasmotrak#endif 8312611Sasmotrak Elf_Addr base_vaddr; 8412611Sasmotrak Elf_Addr base_vlimit; 8512611Sasmotrak Elf_Addr text_vlimit; 8612611Sasmotrak int text_flags; 8712611Sasmotrak caddr_t base_addr; 8812611Sasmotrak Elf_Off data_offset; 8912611Sasmotrak Elf_Addr data_vaddr; 9012611Sasmotrak Elf_Addr data_vlimit; 9112611Sasmotrak int data_flags; 9212611Sasmotrak caddr_t data_addr; 9312611Sasmotrak#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 9412611Sasmotrak Elf_Addr tls_vaddr = 0; /* Noise GCC */ 9512611Sasmotrak#endif 9612611Sasmotrak Elf_Addr phdr_vaddr; 9712611Sasmotrak size_t phdr_memsz; 9812611Sasmotrak caddr_t gap_addr; 9912611Sasmotrak size_t gap_size; 10012611Sasmotrak int i; 10112611Sasmotrak#ifdef RTLD_LOADER 10212611Sasmotrak Elf_Addr clear_vaddr; 10312611Sasmotrak caddr_t clear_addr; 10412611Sasmotrak size_t nclear; 10512611Sasmotrak#endif 10612611Sasmotrak 10712611Sasmotrak if (sb != NULL && sb->st_size < (off_t)sizeof (Elf_Ehdr)) { 10812611Sasmotrak _rtld_error("%s: unrecognized file format1", path); 10912611Sasmotrak return NULL; 11012611Sasmotrak } 11112611Sasmotrak 11212611Sasmotrak obj = _rtld_obj_new(); 11312611Sasmotrak obj->path = xstrdup(path); 11412611Sasmotrak obj->pathlen = strlen(path); 11512611Sasmotrak if (sb != NULL) { 11612611Sasmotrak obj->dev = sb->st_dev; 11712611Sasmotrak obj->ino = sb->st_ino; 11812611Sasmotrak } 11912611Sasmotrak 12012611Sasmotrak ehdr = mmap(NULL, _rtld_pagesz, PROT_READ, MAP_FILE | MAP_SHARED, fd, 12112611Sasmotrak (off_t)0); 12212611Sasmotrak obj->ehdr = ehdr; 12312611Sasmotrak if (ehdr == MAP_FAILED) { 12412611Sasmotrak _rtld_error("%s: read error: %s", path, xstrerror(errno)); 12512611Sasmotrak goto bad; 12612611Sasmotrak } 12712611Sasmotrak /* Make sure the file is valid */ 12812611Sasmotrak if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 || 12912611Sasmotrak ehdr->e_ident[EI_CLASS] != ELFCLASS) { 13012611Sasmotrak _rtld_error("%s: unrecognized file format2 [%x != %x]", path, 13112611Sasmotrak ehdr->e_ident[EI_CLASS], ELFCLASS); 13212611Sasmotrak goto bad; 13312611Sasmotrak } 13412611Sasmotrak /* Elf_e_ident includes class */ 13512611Sasmotrak if (ehdr->e_ident[EI_VERSION] != EV_CURRENT || 13612611Sasmotrak ehdr->e_version != EV_CURRENT || 13712611Sasmotrak ehdr->e_ident[EI_DATA] != ELFDEFNNAME(MACHDEP_ENDIANNESS)) { 13812611Sasmotrak _rtld_error("%s: unsupported file version", path); 13912611Sasmotrak goto bad; 14012611Sasmotrak } 14112611Sasmotrak if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) { 14212611Sasmotrak _rtld_error("%s: unsupported file type", path); 14312611Sasmotrak goto bad; 14412611Sasmotrak } 14512611Sasmotrak switch (ehdr->e_machine) { 14612611Sasmotrak ELFDEFNNAME(MACHDEP_ID_CASES) 14712611Sasmotrak default: 14812611Sasmotrak _rtld_error("%s: unsupported machine", path); 14912611Sasmotrak goto bad; 15012611Sasmotrak } 15112611Sasmotrak 15212611Sasmotrak /* 15312611Sasmotrak * We rely on the program header being in the first page. This is 15412611Sasmotrak * not strictly required by the ABI specification, but it seems to 15512611Sasmotrak * always true in practice. And, it simplifies things considerably. 15612611Sasmotrak */ 15712611Sasmotrak assert(ehdr->e_phentsize == sizeof(Elf_Phdr)); 15812611Sasmotrak assert(ehdr->e_phoff + ehdr->e_phnum * sizeof(Elf_Phdr) <= 15912611Sasmotrak _rtld_pagesz); 16012611Sasmotrak 16112611Sasmotrak /* 16212611Sasmotrak * Scan the program header entries, and save key information. 16312611Sasmotrak * 16412611Sasmotrak * We rely on there being exactly two load segments, text and data, 16512611Sasmotrak * in that order. 16612611Sasmotrak */ 16712611Sasmotrak phdr = (Elf_Phdr *) ((caddr_t)ehdr + ehdr->e_phoff); 16812611Sasmotrak#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 16912611Sasmotrak phtls = NULL; 17012611Sasmotrak#endif 17112611Sasmotrak phsize = ehdr->e_phnum * sizeof(phdr[0]); 17212611Sasmotrak obj->phdr = NULL; 17312611Sasmotrak phdr_vaddr = EA_UNDEF; 17412611Sasmotrak phdr_memsz = 0; 17512611Sasmotrak phlimit = phdr + ehdr->e_phnum; 17612611Sasmotrak nsegs = 0; 17712611Sasmotrak while (phdr < phlimit) { 17812611Sasmotrak switch (phdr->p_type) { 17912611Sasmotrak case PT_INTERP: 18012611Sasmotrak obj->interp = (void *)(uintptr_t)phdr->p_vaddr; 18112611Sasmotrak dbg(("%s: PT_INTERP %p", obj->path, obj->interp)); 18212611Sasmotrak break; 18312611Sasmotrak 18412611Sasmotrak case PT_LOAD: 18512611Sasmotrak if (nsegs < 2) 18612611Sasmotrak segs[nsegs] = phdr; 18712611Sasmotrak ++nsegs; 18812611Sasmotrak dbg(("%s: %s %p phsize %zu", obj->path, "PT_LOAD", 18912611Sasmotrak (void *)(uintptr_t)phdr->p_vaddr, phdr->p_memsz)); 19012611Sasmotrak break; 19112611Sasmotrak 19212611Sasmotrak case PT_PHDR: 19312611Sasmotrak phdr_vaddr = phdr->p_vaddr; 19412611Sasmotrak phdr_memsz = phdr->p_memsz; 19512611Sasmotrak dbg(("%s: %s %p phsize %zu", obj->path, "PT_PHDR", 19612611Sasmotrak (void *)(uintptr_t)phdr->p_vaddr, phdr->p_memsz)); 19712611Sasmotrak break; 19812611Sasmotrak 19912611Sasmotrak case PT_DYNAMIC: 20012611Sasmotrak obj->dynamic = (void *)(uintptr_t)phdr->p_vaddr; 20112611Sasmotrak dbg(("%s: %s %p phsize %zu", obj->path, "PT_DYNAMIC", 20212611Sasmotrak (void *)(uintptr_t)phdr->p_vaddr, phdr->p_memsz)); 20312611Sasmotrak break; 20412611Sasmotrak 20512611Sasmotrak#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 20612611Sasmotrak case PT_TLS: 20712611Sasmotrak phtls = phdr; 20812611Sasmotrak dbg(("%s: %s %p phsize %zu", obj->path, "PT_TLS", 20912611Sasmotrak (void *)(uintptr_t)phdr->p_vaddr, phdr->p_memsz)); 21012611Sasmotrak break; 21112611Sasmotrak#endif 21212611Sasmotrak } 21312611Sasmotrak 21412611Sasmotrak ++phdr; 21512611Sasmotrak } 21612611Sasmotrak phdr = (Elf_Phdr *) ((caddr_t)ehdr + ehdr->e_phoff); 21712611Sasmotrak obj->entry = (void *)(uintptr_t)ehdr->e_entry; 21812611Sasmotrak if (!obj->dynamic) { 21912611Sasmotrak _rtld_error("%s: not dynamically linked", path); 22012611Sasmotrak goto bad; 22112611Sasmotrak } 22212611Sasmotrak if (nsegs != 2) { 22312611Sasmotrak _rtld_error("%s: wrong number of segments (%d != 2)", path, 22412611Sasmotrak nsegs); 22512611Sasmotrak goto bad; 22612611Sasmotrak } 22712611Sasmotrak 22812611Sasmotrak /* 22912611Sasmotrak * Map the entire address space of the object as a file 23012611Sasmotrak * region to stake out our contiguous region and establish a 23112611Sasmotrak * base for relocation. We use a file mapping so that 23212611Sasmotrak * the kernel will give us whatever alignment is appropriate 23312611Sasmotrak * for the platform we're running on. 23412611Sasmotrak * 23512611Sasmotrak * We map it using the text protection, map the data segment 23612611Sasmotrak * into the right place, then map an anon segment for the bss 23712611Sasmotrak * and unmap the gaps left by padding to alignment. 23812611Sasmotrak */ 23912611Sasmotrak 24012611Sasmotrak#ifdef MAP_ALIGNED 24112611Sasmotrak base_alignment = segs[0]->p_align; 24212611Sasmotrak#endif 24312611Sasmotrak base_offset = round_down(segs[0]->p_offset); 24412611Sasmotrak base_vaddr = round_down(segs[0]->p_vaddr); 24512611Sasmotrak base_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_memsz); 24612611Sasmotrak text_vlimit = round_up(segs[0]->p_vaddr + segs[0]->p_memsz); 24712611Sasmotrak text_flags = protflags(segs[0]->p_flags); 24812611Sasmotrak data_offset = round_down(segs[1]->p_offset); 24912611Sasmotrak data_vaddr = round_down(segs[1]->p_vaddr); 25012611Sasmotrak data_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_filesz); 25112611Sasmotrak data_flags = protflags(segs[1]->p_flags); 25212611Sasmotrak#ifdef RTLD_LOADER 25312611Sasmotrak clear_vaddr = segs[1]->p_vaddr + segs[1]->p_filesz; 25412611Sasmotrak#endif 25512611Sasmotrak 25612611Sasmotrak obj->textsize = text_vlimit - base_vaddr; 25712611Sasmotrak obj->vaddrbase = base_vaddr; 25812611Sasmotrak obj->isdynamic = ehdr->e_type == ET_DYN; 25912611Sasmotrak 26012611Sasmotrak#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 26112611Sasmotrak if (phtls != NULL) { 26212611Sasmotrak ++_rtld_tls_dtv_generation; 26312611Sasmotrak obj->tlsindex = ++_rtld_tls_max_index; 26412611Sasmotrak obj->tlssize = phtls->p_memsz; 26512611Sasmotrak obj->tlsalign = phtls->p_align; 26612611Sasmotrak obj->tlsinitsize = phtls->p_filesz; 26712611Sasmotrak tls_vaddr = phtls->p_vaddr; 26812611Sasmotrak } 26912611Sasmotrak#endif 27012611Sasmotrak 27112611Sasmotrak obj->phdr_loaded = false; 27212611Sasmotrak for (i = 0; i < nsegs; i++) { 27312611Sasmotrak if (phdr_vaddr != EA_UNDEF && 27412611Sasmotrak segs[i]->p_vaddr <= phdr_vaddr && 27512611Sasmotrak segs[i]->p_memsz >= phdr_memsz) { 27612611Sasmotrak obj->phdr_loaded = true; 27712611Sasmotrak break; 27812611Sasmotrak } 27912611Sasmotrak if (segs[i]->p_offset <= ehdr->e_phoff && 28012611Sasmotrak segs[i]->p_memsz >= phsize) { 28112611Sasmotrak phdr_vaddr = segs[i]->p_vaddr + ehdr->e_phoff; 28212611Sasmotrak phdr_memsz = phsize; 28312611Sasmotrak obj->phdr_loaded = true; 28412611Sasmotrak break; 28512611Sasmotrak } 28612611Sasmotrak } 28712611Sasmotrak if (obj->phdr_loaded) { 28812611Sasmotrak obj->phdr = (void *)(uintptr_t)phdr_vaddr; 28912611Sasmotrak obj->phsize = phdr_memsz; 29012611Sasmotrak } else { 29112611Sasmotrak Elf_Phdr *buf; 29212611Sasmotrak buf = xmalloc(phsize); 29312611Sasmotrak if (buf == NULL) { 29412611Sasmotrak _rtld_error("%s: cannot allocate program header", path); 29512611Sasmotrak goto bad; 29612611Sasmotrak } 29712611Sasmotrak memcpy(buf, phdr, phsize); 29812611Sasmotrak obj->phdr = buf; 29912611Sasmotrak obj->phsize = phsize; 30012611Sasmotrak } 30112611Sasmotrak dbg(("%s: phdr %p phsize %zu (%s)", obj->path, obj->phdr, obj->phsize, 30212611Sasmotrak obj->phdr_loaded ? "loaded" : "allocated")); 30312611Sasmotrak 30412611Sasmotrak /* Unmap header if it overlaps the first load section. */ 30512611Sasmotrak if (base_offset < _rtld_pagesz) { 30612611Sasmotrak munmap(ehdr, _rtld_pagesz); 30712611Sasmotrak obj->ehdr = MAP_FAILED; 30812611Sasmotrak } 30912611Sasmotrak 31012611Sasmotrak /* 31112611Sasmotrak * Calculate log2 of the base section alignment. 31212611Sasmotrak */ 31312611Sasmotrak mapflags = 0; 31412611Sasmotrak#ifdef MAP_ALIGNED 31512611Sasmotrak if (base_alignment > _rtld_pagesz) { 31612611Sasmotrak unsigned int log2 = 0; 31712611Sasmotrak for (; base_alignment > 1; base_alignment >>= 1) 31812611Sasmotrak log2++; 31912611Sasmotrak mapflags = MAP_ALIGNED(log2); 32012611Sasmotrak } 32112611Sasmotrak#endif 32212611Sasmotrak 32312611Sasmotrak#ifdef RTLD_LOADER 32412611Sasmotrak base_addr = obj->isdynamic ? NULL : (caddr_t)base_vaddr; 32512611Sasmotrak#else 32612611Sasmotrak base_addr = NULL; 32712611Sasmotrak#endif 32812611Sasmotrak mapsize = base_vlimit - base_vaddr; 32912611Sasmotrak mapbase = mmap(base_addr, mapsize, text_flags, 33012611Sasmotrak mapflags | MAP_FILE | MAP_PRIVATE, fd, base_offset); 33112611Sasmotrak if (mapbase == MAP_FAILED) { 33212611Sasmotrak _rtld_error("mmap of entire address space failed: %s", 33312611Sasmotrak xstrerror(errno)); 33412611Sasmotrak goto bad; 33512611Sasmotrak } 33612611Sasmotrak 33712611Sasmotrak /* Overlay the data segment onto the proper region. */ 338 data_addr = mapbase + (data_vaddr - base_vaddr); 339 if (mmap(data_addr, data_vlimit - data_vaddr, data_flags, 340 MAP_FILE | MAP_PRIVATE | MAP_FIXED, fd, data_offset) == 341 MAP_FAILED) { 342 _rtld_error("mmap of data failed: %s", xstrerror(errno)); 343 goto bad; 344 } 345 346 /* Overlay the bss segment onto the proper region. */ 347 if (mmap(mapbase + data_vlimit - base_vaddr, base_vlimit - data_vlimit, 348 data_flags, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) == 349 MAP_FAILED) { 350 _rtld_error("mmap of bss failed: %s", xstrerror(errno)); 351 goto bad; 352 } 353 354 /* Unmap the gap between the text and data. */ 355 gap_addr = mapbase + round_up(text_vlimit - base_vaddr); 356 gap_size = data_addr - gap_addr; 357 if (gap_size != 0 && mprotect(gap_addr, gap_size, PROT_NONE) == -1) { 358 _rtld_error("mprotect of text -> data gap failed: %s", 359 xstrerror(errno)); 360 goto bad; 361 } 362 363#ifdef RTLD_LOADER 364 /* Clear any BSS in the last page of the data segment. */ 365 clear_addr = mapbase + (clear_vaddr - base_vaddr); 366 if ((nclear = data_vlimit - clear_vaddr) > 0) 367 memset(clear_addr, 0, nclear); 368 369 /* Non-file portion of BSS mapped above. */ 370#endif 371 372#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 373 if (phtls != NULL) 374 obj->tlsinit = mapbase + tls_vaddr; 375#endif 376 377 obj->mapbase = mapbase; 378 obj->mapsize = mapsize; 379 obj->relocbase = mapbase - base_vaddr; 380 381 if (obj->dynamic) 382 obj->dynamic = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->dynamic); 383 if (obj->entry) 384 obj->entry = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->entry); 385 if (obj->interp) 386 obj->interp = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->interp); 387 if (obj->phdr_loaded) 388 obj->phdr = (void *)(obj->relocbase + (Elf_Addr)(uintptr_t)obj->phdr); 389 390 return obj; 391 392bad: 393 if (obj->ehdr != MAP_FAILED) 394 munmap(obj->ehdr, _rtld_pagesz); 395 if (mapbase != MAP_FAILED) 396 munmap(mapbase, mapsize); 397 _rtld_obj_free(obj); 398 return NULL; 399} 400 401void 402_rtld_obj_free(Obj_Entry *obj) 403{ 404 Objlist_Entry *elm; 405 406#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 407 if (obj->tls_done) 408 _rtld_tls_offset_free(obj); 409#endif 410 xfree(obj->path); 411 while (obj->needed != NULL) { 412 Needed_Entry *needed = obj->needed; 413 obj->needed = needed->next; 414 xfree(needed); 415 } 416 while ((elm = SIMPLEQ_FIRST(&obj->dldags)) != NULL) { 417 SIMPLEQ_REMOVE_HEAD(&obj->dldags, link); 418 xfree(elm); 419 } 420 while ((elm = SIMPLEQ_FIRST(&obj->dagmembers)) != NULL) { 421 SIMPLEQ_REMOVE_HEAD(&obj->dagmembers, link); 422 xfree(elm); 423 } 424 if (!obj->phdr_loaded) 425 xfree((void *)(uintptr_t)obj->phdr); 426 xfree(obj); 427#ifdef COMBRELOC 428 _rtld_combreloc_reset(obj); 429#endif 430} 431 432Obj_Entry * 433_rtld_obj_new(void) 434{ 435 Obj_Entry *obj; 436 437 obj = CNEW(Obj_Entry); 438 SIMPLEQ_INIT(&obj->dldags); 439 SIMPLEQ_INIT(&obj->dagmembers); 440 return obj; 441} 442 443/* 444 * Given a set of ELF protection flags, return the corresponding protection 445 * flags for MMAP. 446 */ 447static int 448protflags(int elfflags) 449{ 450 int prot = 0; 451 452 if (elfflags & PF_R) 453 prot |= PROT_READ; 454#ifdef RTLD_LOADER 455 if (elfflags & PF_W) 456 prot |= PROT_WRITE; 457#endif 458 if (elfflags & PF_X) 459 prot |= PROT_EXEC; 460 return prot; 461} 462