Is it possible to find out all instances of static initialization in a elf dynamic library. I can dump the array of function pointers in .init_array section via objdump command like this.
objdump -s -j .init_array <libname.so>
Is there a way to map these function pointers back to function names. I have unstripped library with debug symbols. I want to eliminate static initialization as much as possible to improve my library load time.
On x86-64, .init_array contains a list of 8-byte little-endian pointers to static initializers/constructors. The example below has 4 initializers with the addresses - 0x1160, 0x11a7, 0x1231 and 0x12bb:
$ objdump -s -j .init_array a.out
a.out: file format elf64-x86-64
Contents of section .init_array:
3d88 60110000 00000000 a7110000 00000000 `...............
3d98 31120000 00000000 bb120000 00000000 1...............
You can find the initializer function by providing an address from .init_array to objdump. E.g. the address 0x11a7 points to the special function _GLOBAL__sub_I_a (static initializer for the global variable a):
$ objdump -S --start-address=0x11a7 a.out | head
a.out: file format elf64-x86-64
Disassembly of section .text:
00000000000011a7 <_GLOBAL__sub_I_a>:
11a7: f3 0f 1e fa endbr64
11ab: 55 push %rbp
11ac: 48 89 e5 mov %rsp,%rbp
Related
I'm trying to practice a C program (hello.c) calling cobol program (say.cob) from the manual gnucobol.
---- say.cob ------
IDENTIFICATION DIVISION.
PROGRAM-ID. say.
ENVIRONMENT DIVISION.
DATA DIVISION.
LINKAGE SECTION.
01 HELLO PIC X(6).
01 WORLD PIC X(6).
PROCEDURE DIVISION USING HELLO WORLD.
DISPLAY HELLO WORLD.
EXIT PROGRAM.
---- hello.c -
#include <libcob.h>
extern int say(char *hello, char *world);
int
main()
{
int ret;
char hello[7] = "Hello ";
char world[7] = "World!";
cob_init(0, NULL);
ret = say(hello, world);
return ret;
}
C:\Users\S M Rao>gcc -c ‘cob-config --cflags‘ hello.c
gcc: error: `cob-config: No such file or directory
gcc: error: unrecognized command line option '--cflags`'
if I run with commands
cobc -c hello.c
cobc -c -static say.cob
cobc -x -o hello hello.o say.o
getting following error
C:\Users\S M Rao>cobc -x -o hello hello.o say.o
hello.o:hello.c:(.text+0x5c): undefined reference to `say'
collect2.exe: error: ld returned 1 exit status
I can see cob-config is present in gnucobol folder. And in environment variables COB_CONFIG_DIR %COB_MAIN_DIR%\config
what could be the problem? any help please?
cob-config would need to be an executable script, which it commonly is.
As you specify windows paths I assume you use that - and this one cannot run shell scripts. You may get around that with and additional cob-config.bat that executes this shell script, but In this case it will output mingw/wsl/cygwin/... paths that likely cannot be used in the Windows gcc.
Solutions:
run gcc in the matching shell, not from the windows side and have cob-config as an executable script in $PATH
use cobc's feature to call the C processor (and if wanted also the linker) for you: cobc -c hello.c
So I can add a link to a debug symbol file like this objcopy --add-gnu-debuglink=$name.dbg $name, but how can I later retrieve that value again?
I checked with readelf -a and grepped for \.dbg without any luck. Similarly I checked the with objdump -sj .gnu_debuglink (.gnu_debuglink is the section) and could see the value there:
$ objdump -sj .gnu_debuglink helloworld|grep \.dbg
0000 68656c6c 6f776f72 6c642e64 62670000 helloworld.dbg..
However, would there be a command that allows me to extract the retrieve the exact value again (i.e. helloworld.dbg in the above example)? That is the file name only ...
I realize I could use some shell foo here, but it seems odd that an option exists to set this value but none to retrieve it. So I probably just missed it.
You can use readelf directly:
$ readelf --string-dump=.gnu_debuglink helloworld
String dump of section '.gnu_debuglink':
[ 0] helloworld
[ 1b] 9
I do not know what the second entry means (it seems to always be different). To get rid of the header and the offsets, you can use sed:
$ readelf --string-dump=.gnu_debuglink helloworld | sed -n '/]/{s/.* //;p;q}'
helloworld
Something like this should work:
objcopy --output-target=binary --set-section-flags .gnu_debuglink=alloc \
--only-section=.gnu_debuglink helloworld helloworld.dbg
--output-target=binary avoids adding ELF headers. --set-section-flags .gnu_debuglink=alloc is needed because objcopy only writes allocated sections by default (with the binary emulation). And --only-section=.gnu_debuglink finally identifies the answer. See this earlier answer.
Note that the generated file may have a trailing NUL byte and four bytes of CRC, so some post-processing is needed to extract everything up to the first NUL byte (perhaps using head -z -n 1 helloworld.dbg | tr -d '\0' or something similar).
I am new to NASM assembler, and would like to just compile a small example.
global _start
section .text
_start:
mov EAX,1
Compiling it with
$ nasm -f elf64 code.asm ; ld code.o ; ./a.out
Naruszenie ochrony pamięci (zrzut pamięci)
Building works fine but running yields memory access violation.
Here is my assembly code
section .data
msg: db "hello"
section .text
global _start
_start:
nop
mov rax,23
nop
can i access the data located in 'msg' with gdb
The command x/5cb &msg should dump five bytes at the correct address, in both decimal and character notation.
Alternatively, you should be able to use printf "%5.5s\n", &msg as well, substituting in whatever format string you need for other data (a null terminated string, for example, would need only "%s").
This was all tested under CygWin with the following program:
section .data
msg: db "hello"
section .text
global _start
_start: mov eax, 42
ret
When you compile and run that, you get the expected 42 as a return code:
pax> nasm -f elf -o prog.o prog.asm
pax> ld -o prog.exe prog.o
pax> ./prog.exe ; echo $?
42
Starting it in the debugger, you can see the commands needed to get at msg:
pax> gdb prog.exe
GNU gdb (GDB) 7.8
Copyright (C) 2014 Free Software Foundation, Inc.
<blah blah blah>
Reading symbols from prog.exe...(no debugging symbols found)...done.
(gdb) b start
Breakpoint 1 at 0x401000
(gdb) r
Starting program: /cygdrive/c/pax/prog.exe
[New Thread 7416.0x20c0]
Breakpoint 1, 0x00401000 in start ()
(gdb) x/5cb &msg
0x402000 <msg>: 104 'h' 101 'e' 108 'l' 108 'l' 111 'o'
(gdb) printf "%5.5s\n", &msg
hello
Is it possible to dump and investigate shared memory content from Linux? I spoted some strange shared memory segments in a "ipcs -m" output and want to see what is in there.
Also is it possible to determine the creator of this segment. "nattch" seems to be always zero.
Have a look at this tool
Shmcat
It's a good tool for your purpose.
What do you mean with creator? Do you mean the PID of the process? In this last case you can use
ipcs -mp
You'll get this output:
------ Shared Memory Creator/Last-op --------
shmid owner cpid lpid
3211265 root 1857 1866
where
CPID
The process ID of the job that created the shared memory segment.
and
LPID
The process ID of the last job to attach or detach from the shared memory segment or change the semaphore value.
Edit:
I don't think is possible to log those informations with standard tools.
I think we can do in this way.
Suppose we execute the command:
ipcs -m
and get these results
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 3211265 root 644 80 2
Then, with the command grep 3211265 /proc/*/maps, we obtain:
/proc/1862/maps:bla bla bla rw-s 00000000 00:09 3211265 /SYSV00000000 (deleted)
/proc/1863/maps:bla bla bla rw-s 00000000 00:09 3211265 /SYSV00000000 (deleted)
In this way we get the processes that was attached to the segment.
Scanning the elements in /proc/*/maps, you are able to discover the PIDs that are currently attached to a given segment.
You can make use of bash script that log these particular information.