blob: d03d3d2a934516d344e8d58bc0db097986e8070d [file] [log] [blame]
Raghu Gandham405b8022012-07-25 18:16:42 -07001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
Elliott Hughesd070df42013-01-29 16:40:39 -080029#include <elf.h>
Sergey Melnikovc45087b2013-01-25 16:40:13 +040030#include <sys/auxv.h>
Raghu Gandham405b8022012-07-25 18:16:42 -070031#include <sys/types.h>
Pavel Chupinb7beb692012-08-17 12:53:29 +040032#include <link.h>
Raghu Gandham405b8022012-07-25 18:16:42 -070033
Raghu Gandham405b8022012-07-25 18:16:42 -070034/* ld provides this to us in the default link script */
Sergey Melnikovc45087b2013-01-25 16:40:13 +040035extern void* __executable_start;
Raghu Gandham405b8022012-07-25 18:16:42 -070036
Sergey Melnikovc45087b2013-01-25 16:40:13 +040037int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data), void* data) {
Elliott Hughesc6200592013-09-30 18:43:46 -070038 Elf_Ehdr* ehdr = (Elf_Ehdr*) &__executable_start;
Raghu Gandham405b8022012-07-25 18:16:42 -070039
Sergey Melnikovc45087b2013-01-25 16:40:13 +040040 // TODO: again, copied from linker.c. Find a better home for this later.
Raghu Gandham405b8022012-07-25 18:16:42 -070041 if (ehdr->e_ident[EI_MAG0] != ELFMAG0) return -1;
42 if (ehdr->e_ident[EI_MAG1] != ELFMAG1) return -1;
43 if (ehdr->e_ident[EI_MAG2] != ELFMAG2) return -1;
44 if (ehdr->e_ident[EI_MAG3] != ELFMAG3) return -1;
45
Sergey Melnikovc45087b2013-01-25 16:40:13 +040046 // Dynamic binaries get their dl_iterate_phdr from the dynamic linker, but
47 // static binaries get this. We don't have a list of shared objects to
48 // iterate over, since there's really only a single monolithic blob of
49 // code/data, plus optionally a VDSO.
50
51 struct dl_phdr_info exe_info;
52 exe_info.dlpi_addr = 0;
53 exe_info.dlpi_name = NULL;
Elliott Hughesc6200592013-09-30 18:43:46 -070054 exe_info.dlpi_phdr = (Elf_Phdr*) ((unsigned long) ehdr + ehdr->e_phoff);
Sergey Melnikovc45087b2013-01-25 16:40:13 +040055 exe_info.dlpi_phnum = ehdr->e_phnum;
56
57#ifdef AT_SYSINFO_EHDR
58 // Try the executable first.
59 int rc = cb(&exe_info, sizeof(exe_info), data);
60 if (rc != 0) {
61 return rc;
62 }
63
64 // Try the VDSO if that didn't work.
Elliott Hughesc6200592013-09-30 18:43:46 -070065 Elf_Ehdr* ehdr_vdso = (Elf_Ehdr*) getauxval(AT_SYSINFO_EHDR);
Sergey Melnikovc45087b2013-01-25 16:40:13 +040066 struct dl_phdr_info vdso_info;
67 vdso_info.dlpi_addr = 0;
68 vdso_info.dlpi_name = NULL;
Elliott Hughesc6200592013-09-30 18:43:46 -070069 vdso_info.dlpi_phdr = (Elf_Phdr*) ((char*) ehdr_vdso + ehdr_vdso->e_phoff);
Sergey Melnikovc45087b2013-01-25 16:40:13 +040070 vdso_info.dlpi_phnum = ehdr_vdso->e_phnum;
71 for (size_t i = 0; i < vdso_info.dlpi_phnum; ++i) {
72 if (vdso_info.dlpi_phdr[i].p_type == PT_LOAD) {
Elliott Hughesc6200592013-09-30 18:43:46 -070073 vdso_info.dlpi_addr = (Elf_Addr) ehdr_vdso - vdso_info.dlpi_phdr[i].p_vaddr;
Sergey Melnikovc45087b2013-01-25 16:40:13 +040074 break;
75 }
76 }
77 return cb(&vdso_info, sizeof(vdso_info), data);
78#else
79 // There's only the executable to try.
80 return cb(&exe_info, sizeof(exe_info), data);
81#endif
Raghu Gandham405b8022012-07-25 18:16:42 -070082}