15e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine/* Copyright (C) 2007-2011 The Android Open Source Project 25e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine** 35e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine** This software is licensed under the terms of the GNU General Public 45e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine** License version 2, as published by the Free Software Foundation, and 55e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine** may be copied, distributed, and modified under those terms. 65e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine** 75e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine** This program is distributed in the hope that it will be useful, 85e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine** but WITHOUT ANY WARRANTY; without even the implied warranty of 95e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 105e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine** GNU General Public License for more details. 115e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine*/ 125e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 135e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine/* 145e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * Contains implementation of a class DumpFile of routines that implements 155e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * access to a log file. 165e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine */ 175e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 185647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh#include <inttypes.h> 195e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine#include <stdio.h> 205e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine#include <stdlib.h> 215e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine#include <string.h> 225e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine#include <errno.h> 23f9e88edc21c894886747e899dc29c02a28728d65Vladimir Chtchetkine#include "regex/regex.h" 247ecfaaa424d561d670f643993bb9b373db85d832Vladimir Chtchetkine#include "elff/elff_api.h" 255e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 265e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine#include "ndk-stack-parser.h" 275e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 285e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine/* Enumerates states of the crash parser. 295e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine */ 305e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkinetypedef enum NDK_CRASH_PARSER_STATE { 315e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine /* Parser expects the beginning of the crash dump. */ 325e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine EXPECTS_CRASH_DUMP, 335e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine /* Parser expects the build fingerprint, or process and thread information. */ 345e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine EXPECTS_BUILD_FINGREPRINT_OR_PID, 355e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine /* Parser expects the process and thread information. */ 365e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine EXPECTS_PID, 375e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine /* Parser expects the signal information, or the first crash frame. */ 385e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine EXPECTS_SIGNAL_OR_FRAME, 395e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine /* Parser expects a crash frame. */ 405e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine EXPECTS_FRAME, 415e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine} NDK_CRASH_PARSER_STATE; 425e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 435e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine/* Crash parser descriptor. 445e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine */ 455e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkinestruct NdkCrashParser { 465e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine /* Handle to the stream where to print the output. */ 475e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine FILE* out_handle; 485e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 495e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine /* Path to the root folder where symbols are stored. */ 505e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine char* sym_root; 515e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 525e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine /* Current state of the parser. */ 535e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine NDK_CRASH_PARSER_STATE state; 54c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner 55c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner /* Compiled regular expressions */ 56c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner regex_t re_pid_header; 57c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner regex_t re_sig_header; 58c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner regex_t re_frame_header; 595e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine}; 605e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 615e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine/* Crash dumps begin with a string containing this substring. */ 625e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkinestatic const char _crash_dump_header[] = 635e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***"; 645e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 655e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine/* Build fingerprint contains this substring. */ 665e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkinestatic const char _build_fingerprint_header[] = "Build fingerprint:"; 675e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 685e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine/* Regular expression for the process ID information line. */ 697ecfaaa424d561d670f643993bb9b373db85d832Vladimir Chtchetkinestatic const char _pid_header[] = "pid: [0-9]+, tid: [0-9]+.*"; 705e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 715e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine/* Regular expression for the signal information line. */ 727ecfaaa424d561d670f643993bb9b373db85d832Vladimir Chtchetkinestatic const char _sig_header[] = "signal*[ \t][0-9]+"; 735e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 745e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine/* Regular expression for the frame information line. */ 75b3682c489e0c54b1ab05f78e8f91d0642bf975e1Vladimir Chtchetkinestatic const char _frame_header[] = "\\#[0-9]+[ |\t]+[pc|eip]+:*[ |\t]+([0-9a-f]{8})*"; 765e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 775e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine#ifndef min 785e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine#define min(a,b) (((a) < (b)) ? a : b) 795e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine#endif 805e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 815e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine/* Parses a line representing a crash frame. 825e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * This routine will try to obtain source file / line information for the 835e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * frame's address, and print that information to the specified output handle. 845e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * Param: 855e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * parser - NdkCrashParser descriptor, created and initialized with a call to 865e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * NdkCrashParser routine. 875e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * frame - Line containing crash frame. 885e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * Return: 895e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * 0 If source file information has been found and printed, or -1 if that 905e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * information was not available. 915e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine */ 925e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkinestatic int ParseFrame(NdkCrashParser* parser, const char* frame); 935e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 945e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine/* Matches a string against a regular expression. 955e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * Param: 965e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * line - String to matches against the regular expression. 975e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * regex - Regular expression to match the string against. 985e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * match - Upon successful match contains information about the part of the 995e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * string that matches the regular expression. 1005e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * Return: 1015e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * Boolean: 1 if a match has been found, or 0 if match has not been found in 1025e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * the string. 1035e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine */ 104c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turnerstatic int MatchRegex(const char* line, const regex_t* regex, regmatch_t* match); 1055e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 1065e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine/* Returns pointer to the next separator (a space, or a tab) in the string. */ 1075e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkinestatic const char* next_separator(const char* str); 1085e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 1095e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine/* Returns pointer to the next token (a character other than space, or a tab) 1105e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * in the string. 1115e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine */ 1125e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkinestatic const char* next_token(const char* str); 1135e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 1145e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine/* Gets next token from the string. 1155e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * param: 1165e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * str - String where to get the next token from. Note that if string begins 1175e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * with a separator, this routine will return first token after that 1185e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * separator. If string begins with a token, this routine will return next 1195e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * token after that. 1205e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * token - Upon success contains a copy of the next token in the string. 1215e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * size - Size of the 'token' buffer. 1225e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * Return: 1235e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine * Beginning of the returned token in the string. 1245e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine */ 1255e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkinestatic const char* get_next_token(const char* str, char* token, size_t size); 1265e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 12711e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh/* Return pointer to first word "pc", "eip", or "ip" in string "frame" 12811e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh * param: 12911e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh * frame - a line from dump 13011e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh * Return: 13111e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh * The first occurrence of "pc", "eip", or "ip" 13211e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh */ 13311e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsiehstatic const char* find_pc(const char *frame); 13411e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh 1355e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir ChtchetkineNdkCrashParser* 1365e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir ChtchetkineCreateNdkCrashParser(FILE* out_handle, const char* sym_root) 1375e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine{ 138c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner NdkCrashParser* parser; 139c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner 140c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner parser = (NdkCrashParser*)calloc(sizeof(*parser), 1); 141c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner if (parser == NULL) 142c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner return NULL; 143c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner 144c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner parser->out_handle = out_handle; 145c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner parser->state = EXPECTS_CRASH_DUMP; 146c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner 147c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner parser->sym_root = strdup(sym_root); 148c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner if (!parser->sym_root) 149c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner goto BAD_INIT; 150c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner 151c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner if (regcomp(&parser->re_pid_header, _pid_header, REG_EXTENDED | REG_NEWLINE) || 152c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner regcomp(&parser->re_sig_header, _sig_header, REG_EXTENDED | REG_NEWLINE) || 153c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner regcomp(&parser->re_frame_header, _frame_header, REG_EXTENDED | REG_NEWLINE)) 154c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner goto BAD_INIT; 1555e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 1565e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine return parser; 157c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner 158c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' TurnerBAD_INIT: 159c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner DestroyNdkCrashParser(parser); 160c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner return NULL; 1615e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine} 1625e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 1635e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkinevoid 1645e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir ChtchetkineDestroyNdkCrashParser(NdkCrashParser* parser) 1655e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine{ 1665e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine if (parser != NULL) { 167c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner /* Release compiled regular expressions */ 168c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner regfree(&parser->re_frame_header); 169c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner regfree(&parser->re_sig_header); 170c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner regfree(&parser->re_pid_header); 171c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner /* Release symbol path */ 172c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner free(parser->sym_root); 173c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner /* Release parser itself */ 1745e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine free(parser); 1755e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } 1765e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine} 1775e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 1785e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkineint 1795e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir ChtchetkineParseLine(NdkCrashParser* parser, const char* line) 1805e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine{ 1815e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine regmatch_t match; 1825647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh int found = 0; 1835e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 1845e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine if (line == NULL || *line == '\0') { 1855e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine // Nothing to parse. 1865e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine return 1; 1875e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } 1885e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 1895e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine // Lets see if this is the beginning of a crash dump. 1905e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine if (strstr(line, _crash_dump_header) != NULL) { 1915e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine if (parser->state != EXPECTS_CRASH_DUMP) { 1925e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine // Printing another crash dump was in progress. Mark the end of it. 1935e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine fprintf(parser->out_handle, "Crash dump is completed\n\n"); 1945e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } 1955e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 1965e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine // New crash dump begins. 1975e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine fprintf(parser->out_handle, "********** Crash dump: **********\n"); 1985e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine parser->state = EXPECTS_BUILD_FINGREPRINT_OR_PID; 1995e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 2005e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine return 0; 2015e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } 2025e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 2035e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine switch (parser->state) { 2045e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine case EXPECTS_BUILD_FINGREPRINT_OR_PID: 2055e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine if (strstr(line, _build_fingerprint_header) != NULL) { 2065e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine fprintf(parser->out_handle, "%s\n", 2075e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine strstr(line, _build_fingerprint_header)); 2085e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine parser->state = EXPECTS_PID; 2095647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh found = 1; 2105e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } 2115e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine // Let it fall through to the EXPECTS_PID, in case the dump doesn't 2125e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine // contain build fingerprint. 2135e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine case EXPECTS_PID: 214c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner if (MatchRegex(line, &parser->re_pid_header, &match)) { 2155e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine fprintf(parser->out_handle, "%s\n", line + match.rm_so); 2165e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine parser->state = EXPECTS_SIGNAL_OR_FRAME; 2175e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine return 0; 2185e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } else { 2195647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh return !found; 2205e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } 2215e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 2225e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine case EXPECTS_SIGNAL_OR_FRAME: 223c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner if (MatchRegex(line, &parser->re_sig_header, &match)) { 2245e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine fprintf(parser->out_handle, "%s\n", line + match.rm_so); 2255e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine parser->state = EXPECTS_FRAME; 2265647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh found = 1; 2275e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } 2285e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine // Let it fall through to the EXPECTS_FRAME, in case the dump doesn't 2295e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine // contain signal fingerprint. 2305e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine case EXPECTS_FRAME: 23111e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh if (!MatchRegex(line, &parser->re_frame_header, &match)) 2325647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh return !found; 23311e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh // Regex generated by x86_64-w64-mingw32 compiler erroneously match 23411e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh // frame line with #[0-9]+ in "stack:" section even when the line has 23511e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh // no word "pc", "eip", or "ip" in it. 23611e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh // 23711e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh // stack: 23811e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh // I/DEBUG ( 1151): #00 5f09db68 401f01c4 /system/lib/libc.so 23911e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh // 24011e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh // To workaround, let's double check if pc is found! 24111e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh // 24211e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh if (!(find_pc(line))) 24311e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh return !found; 24411e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh 24511e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh parser->state = EXPECTS_FRAME; 24611e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh return ParseFrame(parser, line + match.rm_so); 2475e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 2485e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine default: 2495e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine return 1; 2505e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } 2515e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine} 2525e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 2535e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkinestatic int 254c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' TurnerMatchRegex(const char* line, const regex_t* regex, regmatch_t* match) 2555e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine{ 256c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner int err = regexec(regex, line, 1, match, 0x00400/*REG_TRACE*/); 2575e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine#if 0 25827db2fc052a03217689a4be833ad79458742d7faLogan Chien char rerr[4096]; 25927db2fc052a03217689a4be833ad79458742d7faLogan Chien if (err) { 26027db2fc052a03217689a4be833ad79458742d7faLogan Chien regerror(err, regex, rerr, sizeof(rerr)); 26127db2fc052a03217689a4be833ad79458742d7faLogan Chien fprintf(stderr, "regexec(%s, %s) has failed: %s\n", line, regex, rerr); 26227db2fc052a03217689a4be833ad79458742d7faLogan Chien } 2635e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine#endif 2647ecfaaa424d561d670f643993bb9b373db85d832Vladimir Chtchetkine 265c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner return err == 0; 2665e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine} 2675e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 2685e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkinestatic const char* 2695e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkinenext_separator(const char* str) 2705e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine{ 2715e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine return str + strcspn(str, " \t"); 2725e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine} 2735e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 2745e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkinestatic const char* 2755e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkinenext_token(const char* str) 2765e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine{ 2775e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine str = next_separator(str); 2785e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine return str + strspn(str, " \t"); 2795e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine} 2805e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 2815e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkinestatic const char* 2825e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkineget_next_token(const char* str, char* token, size_t size) 2835e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine{ 2845e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine const char* start = next_token(str); 2855e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine const char* end = next_separator(start); 2865e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine if (start != end) { 287273fd4fcae7d1ee68ff3096108f623c6db6007a8Logan Chien const size_t to_copy = min((size_t)(end - start), (size - 1)); 2885e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine memcpy(token, start, to_copy); 2895e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine token[to_copy] = '\0'; 2905e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine return start; 2915e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } else { 2925e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine return NULL; 2935e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } 2945e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine} 2955e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 29611e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsiehstatic const char * 29711e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsiehfind_pc(const char *frame) 29811e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh{ 29911e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh const char *pcstrs[] = { "pc", "eip", "ip" }; 30011e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh int i; 30111e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh for (i=0; i<sizeof(pcstrs)/sizeof(pcstrs[0]); i++) { 30211e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh const char *p = strstr(frame, pcstrs[i]); 30311e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh // check it's a word, not part of filename or something 30411e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh if (p && p!=frame) { 30511e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh char l = p[-1]; 30611e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh char r = p[strlen(pcstrs[i])]; 30711e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh if ((l==' ' || l=='\t') && (r==' ' || r=='\t')) 30811e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh return p; 30911e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh } 31011e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh } 31111e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh return NULL; 31211e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh} 31311e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh 3145e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkineint 3155e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir ChtchetkineParseFrame(NdkCrashParser* parser, const char* frame) 3165e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine{ 3175e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine uint64_t address; 3185e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine const char* wrk; 3195e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine char* eptr; 3205e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine char pc_address[17]; 3215e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine char module_path[2048]; 322c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner char* module_name; 3235e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine char sym_file[2048]; 3245647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh#if !defined(WITH_LIBBFD) 3255e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine ELFF_HANDLE elff_handle; 3265e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine Elf_AddressInfo pc_info; 3275647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh#else 3285647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh const int ac = 5; 3295647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh char *av[ac]; 3305647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh FILE *f; 3315647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh#endif 3325e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 333c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner fprintf(parser->out_handle, "Stack frame %s", frame); 3345e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 3355e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine // Advance to the instruction pointer token. 33611e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh if ((wrk=find_pc(frame)) == NULL) { 33711e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh fprintf(parser->out_handle, 33811e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh "Parser is unable to locate instruction pointer token.\n"); 33911e5edf52e996b8d10520c67669a9d920f5eaf6fAndrew Hsieh return -1; 3405e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } 3415e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 3425e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine // Next token after the instruction pointer token is its address. 3435e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine wrk = get_next_token(wrk, pc_address, sizeof(pc_address)); 3445e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine // PC address is a hex value. Get it. 3455e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine eptr = pc_address + strlen(pc_address); 3465e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine address = strtoul(pc_address, &eptr, 16); 3475e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 3485e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine // Next token is module path. 3495e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine get_next_token(wrk, module_path, sizeof(module_path)); 3505e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 351c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner // Extract basename of module, we should not care about its path 352c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner // on the device. 353c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner module_name = strrchr(module_path,'/'); 354c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner if (module_name == NULL) 355c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner module_name = module_path; 356c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner else { 357c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner module_name += 1; 358c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner if (*module_name == '\0') { 359c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner /* Trailing slash in the module path, this should not happen */ 360c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner /* Back-off with the full module-path */ 361c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner module_name = module_path; 362c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner } 363c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner } 364c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner 3655e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine // Build path to the symbol file. 3665079ebbb32c44bb3a4bc3602d696521eba6abfffLogan Chien snprintf(sym_file, sizeof(sym_file), "%s/%s", parser->sym_root, module_name); 3675e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine 3685647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh#if defined(WITH_LIBBFD) 3695647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh if ((f=fopen(sym_file, "r")) == NULL) { 3705647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh if (errno == ENOENT) { 3715647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh printf("\n"); 3725647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh } else { 3735647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh printf(": Unable to open symbol file %s. Error (%d): %s\n", 3745647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh sym_file, errno, strerror(errno)); 3755647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh } 3765647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh return -1; 3775647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh } 3785647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh 3795647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh // call addr2line if sym_file exist 3805647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh extern int addr2line_main (int argc, char **argv); 3815647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh 3825647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh av[0] = "ndk-stack"; 3835647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh av[1] = "-fpC"; // f:function, p:pretty-print, C:demangle 3845647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh av[2] = "-e"; // e:exe-filename 3855647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh av[3] = sym_file; 3865647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh av[4] = pc_address; 3875647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh (void)address; 3885647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh 3895647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh printf(": Routine "); 3905647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh return addr2line_main(ac, av); 3915647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh#else 3925e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine // Init ELFF wrapper for the symbol file. 3935e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine elff_handle = elff_init(sym_file); 3945e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine if (elff_handle == NULL) { 395c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner if (errno == ENOENT) { 396c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner fprintf(parser->out_handle, "\n"); 397c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner } else { 398c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner fprintf(parser->out_handle, 399c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner ": Unable to open symbol file %s. Error (%d): %s\n", 400c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner sym_file, errno, strerror(errno)); 401c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner } 4025e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine return -1; 4035e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } 4045e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine // Extract address info from the symbol file. 4055e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine if (!elff_get_pc_address_info(elff_handle, address, &pc_info)) { 4065e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine if (pc_info.dir_name != NULL) { 407c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner fprintf(parser->out_handle, ": Routine %s in %s/%s:%d\n", 4085e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine pc_info.routine_name, pc_info.dir_name, pc_info.file_name, 4095e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine pc_info.line_number); 4105e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } else { 411c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner fprintf(parser->out_handle, ": Routine %s in %s:%d\n", 4125e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine pc_info.routine_name, pc_info.file_name, pc_info.line_number); 4135e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } 4145e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine elff_free_pc_address_info(elff_handle, &pc_info); 4155e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine elff_close(elff_handle); 4165e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine return 0; 4175e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } else { 4185e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine fprintf(parser->out_handle, 419c0bf90ae0f4f84875d0af5d7166b57deb77e57a3David 'Digit' Turner ": Unable to locate routine information for address %x in module %s\n", 4205e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine (uint32_t)address, sym_file); 4215e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine elff_close(elff_handle); 4225e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine return -1; 4235e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine } 4245647b5efe1584bfcb3ed10ca617f7b1d73f63d9bAndrew Hsieh#endif // WITH_LIBBFD 4255e0720014efeafbf6228ae4cd93b3968c1de53fcVladimir Chtchetkine} 426