10266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes/* 20266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * Copyright (C) 2006 The Android Open Source Project 30266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * All rights reserved. 40266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * 50266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * Redistribution and use in source and binary forms, with or without 60266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * modification, are permitted provided that the following conditions 70266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * are met: 80266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * * Redistributions of source code must retain the above copyright 90266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * notice, this list of conditions and the following disclaimer. 100266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * * Redistributions in binary form must reproduce the above copyright 110266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * notice, this list of conditions and the following disclaimer in 120266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * the documentation and/or other materials provided with the 130266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * distribution. 140266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * 150266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 160266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 170266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 180266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 190266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 200266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 210266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 220266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 230266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 240266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 250266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 260266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes * SUCH DAMAGE. 270266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes */ 280266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes 290266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes#include <elf.h> 303002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes#include <string.h> 310266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes#include <sys/auxv.h> 320266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes#include <sys/types.h> 330266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes#include <link.h> 340266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes 350266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes/* ld provides this to us in the default link script */ 360266ae5f884d72da58f33a072e865ba131234a5eElliott Hughesextern "C" void* __executable_start; 370266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes 380266ae5f884d72da58f33a072e865ba131234a5eElliott Hughesint dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data), void* data) { 390266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes ElfW(Ehdr)* ehdr = reinterpret_cast<ElfW(Ehdr)*>(&__executable_start); 400266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes 413002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) { 423002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes return -1; 433002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes } 440266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes 450266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes // Dynamic binaries get their dl_iterate_phdr from the dynamic linker, but 460266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes // static binaries get this. We don't have a list of shared objects to 470266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes // iterate over, since there's really only a single monolithic blob of 480266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes // code/data, plus optionally a VDSO. 490266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes 500266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes struct dl_phdr_info exe_info; 510266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes exe_info.dlpi_addr = 0; 520266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes exe_info.dlpi_name = NULL; 530266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes exe_info.dlpi_phdr = reinterpret_cast<ElfW(Phdr)*>(reinterpret_cast<uintptr_t>(ehdr) + ehdr->e_phoff); 540266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes exe_info.dlpi_phnum = ehdr->e_phnum; 550266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes 563002131da33401cf1b45abbdbec58b7c751fc43aElliott Hughes#if defined(AT_SYSINFO_EHDR) 570266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes // Try the executable first. 580266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes int rc = cb(&exe_info, sizeof(exe_info), data); 590266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes if (rc != 0) { 600266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes return rc; 610266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes } 620266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes 630266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes // Try the VDSO if that didn't work. 640266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes ElfW(Ehdr)* ehdr_vdso = reinterpret_cast<ElfW(Ehdr)*>(getauxval(AT_SYSINFO_EHDR)); 650266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes struct dl_phdr_info vdso_info; 660266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes vdso_info.dlpi_addr = 0; 670266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes vdso_info.dlpi_name = NULL; 680266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes vdso_info.dlpi_phdr = reinterpret_cast<ElfW(Phdr)*>(reinterpret_cast<char*>(ehdr_vdso) + ehdr_vdso->e_phoff); 690266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes vdso_info.dlpi_phnum = ehdr_vdso->e_phnum; 700266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes for (size_t i = 0; i < vdso_info.dlpi_phnum; ++i) { 710266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes if (vdso_info.dlpi_phdr[i].p_type == PT_LOAD) { 720266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes vdso_info.dlpi_addr = (ElfW(Addr)) ehdr_vdso - vdso_info.dlpi_phdr[i].p_vaddr; 730266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes break; 740266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes } 750266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes } 760266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes return cb(&vdso_info, sizeof(vdso_info), data); 770266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes#else 780266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes // There's only the executable to try. 790266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes return cb(&exe_info, sizeof(exe_info), data); 800266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes#endif 810266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes} 82