Breakpoint on the .init Section of a Shared Library - debugging

I tried to run inkscape-0.92.3 in gdb. Precisely, I tried to set a breakpoint on the first address of the .init section in its main shared library (i.e., /usr/lib/inkscape/libinkscape_base.so). The address is 0x7ffff6ebd9d0 based on the information returned by info files. But when I set the breakpoint on this address using b *0x7ffff6ebd9d0, I receive the following error:
Cannot insert breakpoint 1.
Cannot access memory at address 0x7ffff6ebd9d0
This address is the address of the _init function of this library. The same symbol, also, exists in other shared libraries. So I can put a breakpoint on this symbol using b _init, which leads to a lot of sub-breakpoints. This time all breakpoints work fine and I can c(ontinue) until I reach the _init symbol for the libinkscape shared library. Does anybody know the reason for the error in the raw address case?

Does anybody know the reason for the error in the raw address case?
The reason: this address isn't mapped yet (the library hasn't been loaded yet).
It works for break _init case because GDB can check whether any newly-loaded shared library defines that symbol. But it's not smart enough to check whether address 0x7ffff6ebd9d0 becomes breakpoint-able.
You can work around this by using (gdb) set stop-on-solib-events 1. GDB will then stop every time new shared libraries are loaded, before running their initializers.
Once libinkscape_base.so shows up, you will be able to use the address breakpoint as desired.

Related

How to read instructions retired using the perf-interface inside a LKM?

How can I read from the PMU from inside Kernel space?
For a profiling task I need to read the retired instructions provided by the PMU from inside the kernel. The perf_event_open systemcall seems to offer this capability. In my source code I
#include <linux/syscalls.h>
set my parameters for the perf_event_attr struct and call the sys_perf_event_open(). The mentioned header contains the function declaration. When checking "/proc/kallsyms", it is confirmed that there is a systemcall with the name sys_perf_event_open. The symbol is globally available indicated by the T:
ffffffff8113fe70 T sys_perf_event_open
So everything should work as far as I can tell.
Still, when compiling or inserting the LKM I get a warning/error that sys_perf_event_open does not exist.
WARNING: "sys_perf_event_open" [/home/vagrant/mods/lkm_read_pmu/read_pmu.ko] undefined!
What do I need to do in order to get those retired instructions counter?
The /proc/kallsyms file shows all kernel symbols defined in the source. Right, the capital T indicates a global symbol in the text section of the kernel binary, but the meaning of "global" here is according to the C language. That is, it can be used in other files of the kernel itself. You can't call a kernel function from a kernel module just because it's global.
Kernel modules can only use kernel symbols that are exported with EXPORT_SYMBOL in the kernel source code. Since kernel 2.6.0, none of the system calls are exported, so you can't call any of them from a kernel module, including sys_perf_event_open. System calls are really designed to be called from user space. What this all means is that you can't use the perf_event subsystem from within a kernel module.
That said, I think you can modify the kernel to add EXPORT_SYMBOL to sys_perf_event_open. That will make it an exported symbol, which means it can be used from a kernel module.

Loading data segment of already loaded shared library

For global offset table to work, GOT must be at a fixed location from text segment. Now assume that a program needs a shared library. Assume also that the shared library is already loaded by the OS for some other process. Now for our program, since text section of shared library is already loaded, it just needs to load data segment. The shared library text section is mapped back to the virtual address of our process. But what if there is already some data/text or whatever at the fixed offset from the virtual address of our shared library. How does the dynamic linker resolve that conflict? One approach would be to leave R_386_GOTPC in the text section till load time and let the dynamic linker change it the new offset. Is this how it is done in practice.
On GNU, even the same DSO is mapped at different addresses in different processes. No data at all is shared between them. This means that the GOT is just private data (like .data), and is initialized at load time with the proper addresses (either stubs or the proper function addresses with BIND_NOW).
(This assumes that prelink is not in use, which is somewhat broken anyway.)

How to get address of system call entry point?

When a system call is invoked from 64-bit userspace to 64-bit kernel, syscall table is accessed from arch/x86/kernel/entry_64.S, from the system_call assembly entry point. How can I get the virtual/physical address of this "system_call()" routine?
In other words, I want to know the address of entry point used by all system calls. I tried looking at kallsyms file but couldn't find it there. Perhaps, it has another name in kallsyms?
Reference: https://lwn.net/Articles/604287/
What do you need this for? Are you sure you were inspecting kallsyms of the same kernel which was used in the article?
Figuring out what the func got renamed to is left as an exercise for the reader.

Getting address of symbol from kernel's symbol table

arif#khost:~/src/linux$ global -x ip_rcv_finish
ip_rcv_finish 319 net/ipv4/ip_input.c static int ip_rcv_finish(struct sk_buff *skb)
Now if i want to use this function i need to initialize a pointer to this function.
To be able to do that i need the address of the function.
I've seen that from user space i can read /proc/kallsyms to get an address of a symbol. Is their any similar mechanism exist where i can read the symbol table to extract a symbol's address from kernel space?
Depending on your kernel version, you can use kallsyms_lookup_name and/or kallsyms_on_each_symbol to obtain the addresses of the symbols from code running in the kernel space.
This only works if CONFIG_KALLSYMS is set in the kernel configuration.
Note that I would not recommend looking up the addresses of the functions to be called though unless there is no better way (kernel API) to do what you would like to. Still, if nothing else helps, kallsyms_*() API may be the way to go.

Windbg with xp embedded, ntdll.dll symbols fail, other symbols affected?

I am using windbg with xp embedded. Attempting to fetch the operating system symbols fails with the message "Symbol file could not be found. Defaulted to export symbols for ntdll.dll". (Is this typical for xp embedded???)
I have no problem locating and loading symbols and source for my own code. However stepping through the code suggests there is a severe mismatch between the code and the symbol file as the location of variables in memory as returned by dv does not appear to agree with the actual memory contents (e.g. assign a variable, but afterwards, the address that dv claims corresponds to it doesn't appears unchanged).
My sympath lists the symbol directory first, then the cache, then the server so cached symbol files shouldn't be interfering.
Is this a latent effect of not finding the ntdll symbol files and using another one that doesn't match correctly or is there something else that could be causing this?
Example:
.sympath D:/Symbols
.symfix+
.srcpath D:/Symbols ** Yes, currently the source is in with the symbols
.reload
** (defaults to export symbols for ntdll.dll since symbol file can't be found)
bp 00401000 (break at a constructor)
g
(program runs till it hits constructor)
l+t
dv /i /t /V ** look up this pointer memory location to check constructor
** We bring up a memory window at the location the this pointer refers to and
** step through the code, but no changes appear in that memory window
** moreover a local LARGE_INTEGER whose value is set with QueryPerformanceCounter
** also appears unchanged after the call
** when the constructor returns we assign the memory address returned by
** new to a global pointer, whose memory address we look up with dt, but
** after the call that address still has 0 in it
Can anyone tell me how to actually fix this?
As a side note we actually run cdb as a server on the xp embedded machine and use the "connect to remote session" option of windbg. The above commands are all executed through windbg.
Executing !sym noisy before the .reload will let you know why it's not finding symbols for ntdll.dll. It's entirely possible that they're simply not indexed on the symbol server, which generally means you are out of luck (there really isn't anyone to contact to get this fixed unfortunately).
As for your other symbol issues:
1) Is this the release build of your code? If so, it's entirely expected
2) If it is the debug build, are you 100% sure that the source you're pointing to matches the target machine? Make sure you're 100% before answering :)
-scott

Resources