"failstar" sounds like a name for a cruise liner from the 80s. As "*" isn't a desirable part of directory names, just name the whole thing "fail/", the core parts being stored in "fail/core/". Additionally fixing two build system dependency issues: - missing jobserver -> protomessages dependency - broken bochs -> fail dependency (add_custom_target DEPENDS only allows plain file dependencies ... cmake for the win) git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@956 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
164 lines
4.1 KiB
C++
164 lines
4.1 KiB
C++
/* Code sample: Using libdwarf for getting the address of a function
|
|
** from DWARF in an ELF executable.
|
|
** Not much error-handling or resource-freeing is done here...
|
|
**
|
|
** Eli Bendersky (http://eli.thegreenplace.net)
|
|
** This code is in the public domain.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <dwarf.h>
|
|
#include <libdwarf.h>
|
|
|
|
|
|
void die(char* fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start(args, fmt);
|
|
vfprintf(stderr, fmt, args);
|
|
va_end(args);
|
|
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
|
|
/* List a function if it's in the given DIE.
|
|
*/
|
|
void list_func_in_die(Dwarf_Debug dgb, Dwarf_Die the_die)
|
|
{
|
|
char* die_name = 0;
|
|
const char* tag_name = 0;
|
|
Dwarf_Error err;
|
|
Dwarf_Half tag;
|
|
Dwarf_Attribute* attrs;
|
|
Dwarf_Addr lowpc, highpc;
|
|
Dwarf_Signed attrcount, i;
|
|
int rc = dwarf_diename(the_die, &die_name, &err);
|
|
|
|
if (rc == DW_DLV_ERROR)
|
|
die("Error in dwarf_diename\n");
|
|
else if (rc == DW_DLV_NO_ENTRY)
|
|
return;
|
|
|
|
if (dwarf_tag(the_die, &tag, &err) != DW_DLV_OK)
|
|
die("Error in dwarf_tag\n");
|
|
|
|
/* Only interested in subprogram DIEs here */
|
|
if (tag != DW_TAG_subprogram)
|
|
return;
|
|
|
|
if (dwarf_get_TAG_name(tag, &tag_name) != DW_DLV_OK)
|
|
die("Error in dwarf_get_TAG_name\n");
|
|
|
|
printf("DW_TAG_subprogram: '%s'\n", die_name);
|
|
|
|
/* Grab the DIEs attributes for display */
|
|
if (dwarf_attrlist(the_die, &attrs, &attrcount, &err) != DW_DLV_OK)
|
|
die("Error in dwarf_attlist\n");
|
|
|
|
for (i = 0; i < attrcount; ++i) {
|
|
Dwarf_Half attrcode;
|
|
if (dwarf_whatattr(attrs[i], &attrcode, &err) != DW_DLV_OK)
|
|
die("Error in dwarf_whatattr\n");
|
|
|
|
/* We only take some of the attributes for display here.
|
|
** More can be picked with appropriate tag constants.
|
|
*/
|
|
if (attrcode == DW_AT_low_pc)
|
|
dwarf_formaddr(attrs[i], &lowpc, 0);
|
|
else if (attrcode == DW_AT_high_pc)
|
|
dwarf_formaddr(attrs[i], &highpc, 0);
|
|
}
|
|
|
|
printf("low pc : 0x%08llx\n", lowpc);
|
|
printf("high pc : 0x%08llx\n", highpc);
|
|
}
|
|
|
|
|
|
/* List all the functions from the file represented by the given descriptor.
|
|
*/
|
|
void list_funcs_in_file(Dwarf_Debug dbg)
|
|
{
|
|
Dwarf_Unsigned cu_header_length, abbrev_offset, next_cu_header;
|
|
Dwarf_Half version_stamp, address_size;
|
|
Dwarf_Error err;
|
|
Dwarf_Die no_die = 0, cu_die, child_die;
|
|
|
|
/* Find compilation unit header */
|
|
while (dwarf_next_cu_header(
|
|
dbg,
|
|
&cu_header_length,
|
|
&version_stamp,
|
|
&abbrev_offset,
|
|
&address_size,
|
|
&next_cu_header,
|
|
&err) != DW_DLV_ERROR) {
|
|
|
|
/* Expect the CU to have a single sibling - a DIE */
|
|
if (dwarf_siblingof(dbg, no_die, &cu_die, &err) == DW_DLV_ERROR)
|
|
die("Error getting sibling of CU\n");
|
|
|
|
/* Expect the CU DIE to have children */
|
|
if (dwarf_child(cu_die, &child_die, &err) == DW_DLV_ERROR)
|
|
die("Error getting child of CU DIE\n");
|
|
|
|
/* Now go over all children DIEs */
|
|
while (1) {
|
|
int rc;
|
|
list_func_in_die(dbg, child_die);
|
|
|
|
rc = dwarf_siblingof(dbg, child_die, &child_die, &err);
|
|
|
|
if (rc == DW_DLV_ERROR)
|
|
die("Error getting sibling of DIE\n");
|
|
else if (rc == DW_DLV_NO_ENTRY)
|
|
break; /* done */
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
Dwarf_Debug dbg = 0;
|
|
Dwarf_Error err;
|
|
const char* progname;
|
|
int fd = -1;
|
|
|
|
if (argc < 2) {
|
|
fprintf(stderr, "Expected a program name as argument\n");
|
|
return 1;
|
|
}
|
|
|
|
progname = argv[1];
|
|
if ((fd = open(progname, O_RDONLY)) < 0) {
|
|
perror("open");
|
|
return 1;
|
|
}
|
|
|
|
if (dwarf_init(fd, DW_DLC_READ, 0, 0, &dbg, &err) != DW_DLV_OK) {
|
|
fprintf(stderr, "Failed DWARF initialization\n");
|
|
return 1;
|
|
}
|
|
|
|
list_funcs_in_file(dbg);
|
|
|
|
if (dwarf_finish(dbg, &err) != DW_DLV_OK) {
|
|
fprintf(stderr, "Failed DWARF finalization\n");
|
|
return 1;
|
|
}
|
|
|
|
close(fd);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|