1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <elf.h> 18#include <errno.h> 19#include <inttypes.h> 20#include <stdio.h> 21#include <string.h> 22#include <sys/stat.h> 23#include <sys/types.h> 24#include <unistd.h> 25 26#include <unwindstack/Elf.h> 27#include <unwindstack/Log.h> 28#include <unwindstack/Memory.h> 29 30int main(int argc, char** argv) { 31 if (argc != 2) { 32 printf("Need to pass the name of an elf file to the program.\n"); 33 return 1; 34 } 35 36 struct stat st; 37 if (stat(argv[1], &st) == -1) { 38 printf("Cannot stat %s: %s\n", argv[1], strerror(errno)); 39 return 1; 40 } 41 if (!S_ISREG(st.st_mode)) { 42 printf("%s is not a regular file.\n", argv[1]); 43 return 1; 44 } 45 46 // Send all log messages to stdout. 47 unwindstack::log_to_stdout(true); 48 49 unwindstack::MemoryFileAtOffset* memory = new unwindstack::MemoryFileAtOffset; 50 if (!memory->Init(argv[1], 0)) { 51 printf("Failed to init\n"); 52 return 1; 53 } 54 55 unwindstack::Elf elf(memory); 56 if (!elf.Init() || !elf.valid()) { 57 printf("%s is not a valid elf file.\n", argv[1]); 58 return 1; 59 } 60 61 switch (elf.machine_type()) { 62 case EM_ARM: 63 printf("ABI: arm\n"); 64 break; 65 case EM_AARCH64: 66 printf("ABI: arm64\n"); 67 break; 68 case EM_386: 69 printf("ABI: x86\n"); 70 break; 71 case EM_X86_64: 72 printf("ABI: x86_64\n"); 73 break; 74 default: 75 printf("ABI: unknown\n"); 76 return 1; 77 } 78 79 // This is a crude way to get the symbols in order. 80 std::string name; 81 uint64_t load_bias = elf.interface()->load_bias(); 82 for (const auto& entry : elf.interface()->pt_loads()) { 83 uint64_t start = entry.second.offset + load_bias; 84 uint64_t end = entry.second.table_size + load_bias; 85 for (uint64_t addr = start; addr < end; addr += 4) { 86 std::string cur_name; 87 uint64_t func_offset; 88 if (elf.GetFunctionName(addr, &cur_name, &func_offset)) { 89 if (cur_name != name) { 90 printf("<0x%" PRIx64 "> Function: %s\n", addr - func_offset, cur_name.c_str()); 91 } 92 name = cur_name; 93 } 94 } 95 } 96 97 return 0; 98} 99