From: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
To: elfutils-devel@lists.fedorahosted.org
Subject: Help with getting CFA for split debuginfo files
Date: Tue, 06 May 2014 16:32:45 -0700 [thread overview]
Message-ID: <20140506233245.GA32007@us.ibm.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 2860 bytes --]
We are trying to write a function on PowerPC, that, given a filename
(ELF binary) and PC (program counter), returns:
- 0 if the return address at the given PC is saved on stack,
- 1 if the RA is still in LR and no new frame was allocated
- 2 if a RA is in LR but new frame was allocated and yet to
be used.
Referring to 'elfutils.git/tests/addrcfi.c', we wrote this program
that seems to work (i.e is consistent with 'readelf -wF) for a single
a.out file:
Eg:
$ readelf -wF ./crc5
---- <snip>
Contents of the .debug_frame section:
00000000 0000000c ffffffff CIE "" cf=4 df=-8 ra=65
LOC CFA
0000000000000000 r1+0
00000010 00000024 00000000 FDE cie=00000000 pc=10000ca4..10000d04
LOC CFA r31 ra
0000000010000ca4 r1+0 u u
>>>> 0000000010000cb4 r1+128 c-8 c+16
0000000010000cb8 r31+128 c-8 c+16
0000000010000ce8 r1+0 c-8 c+16
---- <snip>
$ ./crc5 0000000010000cb0 0000000010000cb4 ./crc5
Ret Address 0x10000cb0 is in LR
Ret Address 0x10000cb1 is in LR
Ret Address 0x10000cb2 is in LR
Ret Address 0x10000cb3 is in LR
Ret Address 0x10000cb4 is NOT in LR
i.e for PC 0x10000cb3, return address is in LR, and for PC 0x10000cb4
return address is on the stack (c1+16).
But I am not sure how to extend the code to work with PC value that points
to, say __random(), in glibc.
I have these installed:
glibc-common-2.18-11.fc20.ppc64p7
glibc-2.18-11.fc20.ppc64p7
glibc-headers-2.18-11.fc20.ppc64p7
glibc-debuginfo-common-2.18-11.fc20.ppc64p7
glibc-devel-2.18-11.fc20.ppc64p7
glibc-debuginfo-2.18-11.fc20.ppc64p7
$ objdump -D /usr/lib64/libc-2.18.so
....
00000080a7be3bf0 <.__random>:
80a7be3bf0: 7c 08 02 a6 mflr r0
80a7be3bf4: fb e1 ff f8 std r31,-8(r1)
80a7be3bf8: 60 00 00 00 nop
80a7be3bfc: 39 00 00 01 li r8,1
80a7be3c00: 3b e2 9a f0 addi r31,r2,-25872
80a7be3c04: 39 40 00 00 li r10,0
80a7be3c08: f8 01 00 10 std r0,16(r1)
80a7be3c0c: f8 21 ff 71 stdu r1,-144(r1)
80a7be3c10: 7d 20 f8 29 lwarx r9,0,r31,1
80a7be3c14: 7c 09 50 00 cmpw r9,r10
80a7be3c18: 40 82 00 0c bne 80a7be3c24 <.__random+0x34>
80a7be3c1c: 7d 00 f9 2d stwcx. r8,0,r31
>>>> 80a7be3c20: 40 c2 ff f0 bne- 80a7be3c10 <.__random+0x20>
....
$ ./crc5 80a7be3c20 80a7be3c20 /usr/lib64/libc-2.18.so
Error dwarf_cfi_addrframe(): : no matching address range
Error with addr 0x80a7be3c20
$ ./crc5 80a7be3c20 80a7be3c20 /usr/lib/debug/lib64/libc.so.6.debug
Error dwfl_addrmodule: no error
Error with addr 0x80a7be3c20
Pls find the code attached. Appreciate any comments on how to extend it
to work with split debug info files.
Sukadev
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: crc5.c --]
[-- Type: text/x-csrc, Size: 3307 bytes --]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <dwarf.h>
#include <elfutils/libdwfl.h>
#define INTUSE(x) x
/* From libdwfl/argp-std.c */
static char *debuginfo_path;
static const Dwfl_Callbacks offline_callbacks =
{
.find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
.debuginfo_path = &debuginfo_path,
.section_address = INTUSE(dwfl_offline_section_address),
};
void error(char *msg)
{
printf("Error %s: %s\n", msg, dwarf_errmsg(-1));
}
/*
* @ra_regno contains the return address. We need to find
* the expression for that register
*/
static int
check_return_reg(int ra_regno, Dwarf_Frame *frame)
{
Dwarf_Op ops_mem[2];
Dwarf_Op dummy;
Dwarf_Op *ops = &dummy;
size_t nops;
int i, result;
result = dwarf_frame_register(frame, ra_regno, ops_mem, &ops, &nops);
if (result < 0) {
error("dwarf_frame_register()");
return -1;
}
if (nops != 0 || ops != NULL)
return 0; /* return address on the stack */
/*
* Return address in LR. Check if a frame was allocated
* but not yet used.
*/
result = dwarf_frame_cfa(frame, &ops, &nops);
if (result < 0) {
error("dwarf_frame_cfa()");
return -1;
}
if (nops == 1 && ops[0].atom == DW_OP_bregx &&
ops[0].number == 1 && ops[0].number2 == 0)
return 1; /* no new frame allocated */
return 2; /* new frame allocated, but not yet used */
}
/*
* Return 1 if the address @pc is in LR. O otherwise.
* Return -1 in case of errors
*/
int check_ret_addr_in_lr(const char *exec_file, Dwarf_Addr pc)
{
int result;
Dwfl *dwfl;
Dwfl_Module *mod;
Dwarf_CFI *cfi;
Dwarf_Frame *frame;
Dwarf_Addr bias;
int ra_regno;
Dwarf_Addr start = pc;
Dwarf_Addr end = pc;
bool signalp;
dwfl = dwfl_begin(&offline_callbacks);
if (dwfl == NULL) {
error("dwfl_begin() failed\n");
return -1;
}
if (dwfl_report_offline(dwfl, "", exec_file, -1) == NULL) {
error("dwfl_report_offline()");
return -1;
}
mod = dwfl_addrmodule(dwfl, pc);
if (!mod) {
error("dwfl_addrmodule");
return -1;
}
cfi = dwfl_module_dwarf_cfi(mod, &bias);
if (!cfi) {
printf("No dwarf cfi, trying eh cfi\n");
cfi = dwfl_module_eh_cfi(mod, &bias); // CHECK
if (!cfi) {
error("dwfl_module_dwarf_cfi(): no CFI -");
return -1;
}
}
result = dwarf_cfi_addrframe(cfi, pc - bias, &frame);
if (result != 0) {
error("dwarf_cfi_addrframe(): ");
return -1;
}
ra_regno = dwarf_frame_info(frame, &start, &end, &signalp);
if (ra_regno < 0) {
printf("\treturn address register unavailable (%s)\n",
dwarf_errmsg (0));
return -1;
}
return check_return_reg(ra_regno, frame);
}
int
main(int argc, const char *argv[])
{
int rc;
const char *exec_file;
Dwarf_Addr pc = 0x100006c4;
Dwarf_Addr end;
if (argc > 1)
pc = strtol(argv[1], NULL, 16);
end = pc;
if (argc > 2)
end = strtol(argv[2], NULL, 16);
exec_file = "a.out";
if (argc > 3)
exec_file = argv[3];
while (pc <= end) {
rc = check_ret_addr_in_lr(exec_file, pc);
if (rc < 0)
printf("Error with addr 0x%" PRIx64 "\n", pc);
else if (rc == 1)
printf("Ret Address 0x%" PRIx64 " is in LR\n", pc);
else if (rc == 2)
printf("Ret Address 0x%" PRIx64 " is in LR, slot1 invalid\n", pc);
else
printf("Ret Address 0x%" PRIx64 " is NOT in LR\n", pc);
pc += 1;
}
}
next reply other threads:[~2014-05-06 23:32 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-05-06 23:32 Sukadev Bhattiprolu [this message]
2014-05-07 9:48 Mark Wielaard
2014-05-07 22:06 Sukadev Bhattiprolu
2014-05-08 6:54 Mark Wielaard
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140506233245.GA32007@us.ibm.com \
--to=sukadev@linux.vnet.ibm.com \
--cc=elfutils-devel@lists.fedorahosted.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).