public inbox for elfutils@sourceware.org
 help / color / mirror / Atom feed
* Re: Help with getting CFA for split debuginfo files
@ 2014-05-07 22:06 Sukadev Bhattiprolu
  0 siblings, 0 replies; 4+ messages in thread
From: Sukadev Bhattiprolu @ 2014-05-07 22:06 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 1671 bytes --]

Mark Wielaard [mjw@redhat.com] wrote:
| > 	$ ./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.
| 
| The first invocation should work (it will find the separate debug info
| file that matches itself through dwfl_standard_find_debuginfo).

Thanks for looking into it.

I switched the order the dwfl_module_eh_cfi() and dwfl_module_dwarf_cfi()
and did not seem to help, until I noticed that 'bias' is always 0 for
the dwarf_cfi but 0x10000 for the eh_cfi (for the examples I tried).

I had code like this before:

	        cfi = dwfl_module_eh_cfi(mod, &bias);

		result = dwarf_cfi_addrframe(cfi, pc - bias, &frame);

Changing 'pc - bias' to just 'pc' for the eh_cfi, the program seems to work
for several addresses in libc. Does that change make sense ?

| 
| You find the .debug_frame CFI through dwfl_module_dwarf_cfi and then
| lookup the address using dwarf_cfi_addrframe. The .debug_frame
| apparently exists but doesn't contain the requested address. You should
| then try to find it through the .eh_frame CFI using dwfl_module_eh_cfi
| (or just swap the dwfl_module_dwarf_cfi and dwfl_module_eh_cfi calls
| since on fedora the .eh_frame should always be complete because GCC uses
| -fasynchronous-unwind-tables by default).
| 
| Cheers,
| 
| Mark
| 


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Help with getting CFA for split debuginfo files
@ 2014-05-08  6:54 Mark Wielaard
  0 siblings, 0 replies; 4+ messages in thread
From: Mark Wielaard @ 2014-05-08  6:54 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 1901 bytes --]

On Wed, 2014-05-07 at 15:06 -0700, Sukadev Bhattiprolu wrote:
> Mark Wielaard [mjw@redhat.com] wrote:
> | > 	$ ./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.
> | 
> | The first invocation should work (it will find the separate debug info
> | file that matches itself through dwfl_standard_find_debuginfo).
> 
> Thanks for looking into it.
> 
> I switched the order the dwfl_module_eh_cfi() and dwfl_module_dwarf_cfi()
> and did not seem to help, until I noticed that 'bias' is always 0 for
> the dwarf_cfi but 0x10000 for the eh_cfi (for the examples I tried).
> 
> I had code like this before:
> 
> 	        cfi = dwfl_module_eh_cfi(mod, &bias);
> 
> 		result = dwarf_cfi_addrframe(cfi, pc - bias, &frame);
> 
> Changing 'pc - bias' to just 'pc' for the eh_cfi, the program seems to work
> for several addresses in libc. Does that change make sense ?

Yes, that makes sense if you take the addresses directly from the file.
The bias given by dwfl_module_eh_cfi or dwfl_module_dwarf_cfi is the
difference between addresses as used in the CFI (from the Elf or Dwarf
file - which might be different depending on whether the Dwarf comes
from a separate debuginfo file or not) and where the Dwfl_Module is
"loaded". The difference matters for example if you construct a Dwfl
from a life process or core file. Then the addresses found in the
process or core might have to be translated back to the addresses as
found in the underlying Elf or Dwarf file.

Cheers,

Mark


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Help with getting CFA for split debuginfo files
@ 2014-05-07  9:48 Mark Wielaard
  0 siblings, 0 replies; 4+ messages in thread
From: Mark Wielaard @ 2014-05-07  9:48 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 2331 bytes --]

Hi Sukadev,

On Tue, 2014-05-06 at 16:32 -0700, Sukadev Bhattiprolu wrote:
> 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.

The first invocation should work (it will find the separate debug info
file that matches itself through dwfl_standard_find_debuginfo).

You find the .debug_frame CFI through dwfl_module_dwarf_cfi and then
lookup the address using dwarf_cfi_addrframe. The .debug_frame
apparently exists but doesn't contain the requested address. You should
then try to find it through the .eh_frame CFI using dwfl_module_eh_cfi
(or just swap the dwfl_module_dwarf_cfi and dwfl_module_eh_cfi calls
since on fedora the .eh_frame should always be complete because GCC uses
-fasynchronous-unwind-tables by default).

Cheers,

Mark



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Help with getting CFA for split debuginfo files
@ 2014-05-06 23:32 Sukadev Bhattiprolu
  0 siblings, 0 replies; 4+ messages in thread
From: Sukadev Bhattiprolu @ 2014-05-06 23:32 UTC (permalink / raw)
  To: elfutils-devel

[-- 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;
	}
}

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2014-05-08  6:54 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-07 22:06 Help with getting CFA for split debuginfo files Sukadev Bhattiprolu
  -- strict thread matches above, loose matches on Subject: below --
2014-05-08  6:54 Mark Wielaard
2014-05-07  9:48 Mark Wielaard
2014-05-06 23:32 Sukadev Bhattiprolu

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).