I have the following code which is compiled with -g option.
$ cat main.c
/* vim: set noexpandtab tabstop=2: */
#include <stdio.h>
int U_var;
int I_var=42;
const int C_var=2;
static void inc_U_var() {
U_var+=C_var;
}
void inc_I_var() {
I_var+=C_var;
}
int main() {
inc_U_var();
inc_I_var();
return 0;
}
In gdb, the constant C_var is shown as $2. Is there a way to preserve the const variable name in the disassembly code? Thanks.
(gdb) disassemble inc_I_var
Dump of assembler code for function inc_I_var:
0x0000000100000ec0 <+0>: push %rbp
0x0000000100000ec1 <+1>: mov %rsp,%rbp
0x0000000100000ec4 <+4>: mov 0x156(%rip),%eax # 0x100001020 <I_var>
0x0000000100000eca <+10>: add $0x2,%eax
0x0000000100000ecd <+13>: mov %eax,0x14d(%rip) # 0x100001020 <I_var>
0x0000000100000ed3 <+19>: pop %rbp
0x0000000100000ed4 <+20>: retq
End of assembler dump.
(gdb) list inc_I_var
7
8 static void inc_U_var() {
9 U_var+=C_var;
10 }
11
12 void inc_I_var() {
13 I_var+=C_var;
14 }
15
16 int main() {
How to show const variable name in disassemble'd code in gdb?
You cannot : at compile time the const int C_vars is replaced by its value, so in the assembler you have $2 rather than an access to C_var, gdb has no way to know where 2 comes from
Related
In Windows, a segment error occurs when an executable file accesses a thread local variable in the dynamic library in extern mode.This problem occurs when clang is used, but not when gcc is used.
// test.c
__thread int g_cnt = 1;
Compile the dynamic library:
clang --target=x86_64-pc-windows-gnu test.c -shared -o libtest.dll
// main.c
#include <stdio.h>
extern __thread int g_cnt;
int get_cnt()
{
return g_cnt;
}
int main() {
int cnt = get_cnt();
printf("cnt = %d\n", cnt);
return 0;
}
Generating an Executable File:
clang --target=x86_64-pc-windows-gnu main.c -L.\ -ltest -o main.exe
Segment error while accessing thread local variables
Thread 1 received signal SIGSEGV, Segmentation fault.
0x00007ff6bf5717e5 in get_cnt ()
(gdb) disassemble
Dump of assembler code for function get_cnt:
0x00007ff6bf5717d0 <+0>: mov 0xe8ea(%rip),%eax # 0x7ff6bf5800c0 <_tls_index>
0x00007ff6bf5717d6 <+6>: mov %eax,%ecx
0x00007ff6bf5717d8 <+8>: mov %gs:0x58,%rax
0x00007ff6bf5717e1 <+17>: mov (%rax,%rcx,8),%rax
=> 0x00007ff6bf5717e5 <+21>: mov 0x7f5782f0(%rax),%eax
0x00007ff6bf5717eb <+27>: ret
0x00007ff6bf5717ec <+28>: nopl 0x0(%rax)
End of assembler dump.
(gdb) p *0x7ff6bf5800c0
$1 = 0
Is this a clang bug?
The version of clang I tested was 12.0.1
Mingw uses x86_64-posix-seh-gcc-12.1.0-mingw-w64msvcrt-10.0.0.
I am writing a utility to get the memory used by the process while getting into the function and while getting out of the function for each function. I plan to do it in the _penter and _pexit functions. Is there a simple way to get the name of the function in _penter and _pexit? I have the pdb file of my executable. Can somebody help me to get it using SymGetSymFromAddr64 and StackWalk64?
I was also looking for a solution and I couldn't find it but managed to solve it myself here is what I used
Configuration Properties > C/C++ > Command Line
Add compiler option to Additional Options box
Like so
Add flag /Gh for _penter hook
Add flag /GH for _pexit hook
Code I use for tracing / logging
#include <intrin.h>
extern "C" void __declspec(naked) __cdecl _penter(void) {
__asm {
push ebp; // standard prolog
mov ebp, esp;
sub esp, __LOCAL_SIZE
pushad; // save registers
}
// _ReturnAddress always returns the address directly after the call, but that is not the start of the function!
PBYTE addr;
addr = (PBYTE)_ReturnAddress() - 5;
SYMBOL_INFO* mysymbol;
HANDLE process;
process = GetCurrentProcess();
SymInitialize(process, NULL, TRUE);
mysymbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
mysymbol->MaxNameLen = 255;
mysymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
SymFromAddr(process, (DWORD64)((void*)addr), 0, mysymbol);
myprintf("Entered Function: %s [0x%X]\n", mysymbol->Name, addr);
_asm {
popad; // restore regs
mov esp, ebp; // standard epilog
pop ebp;
ret;
}
}
extern "C" void __declspec(naked) __cdecl _pexit(void) {
__asm {
push ebp; // standard prolog
mov ebp, esp;
sub esp, __LOCAL_SIZE
pushad; // save registers
}
// _ReturnAddress always returns the address directly after the call, but that is not the start of the function!
PBYTE addr;
addr = (PBYTE)_ReturnAddress() - 5;
SYMBOL_INFO* mysymbol;
HANDLE process;
process = GetCurrentProcess();
SymInitialize(process, NULL, TRUE);
mysymbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
mysymbol->MaxNameLen = 255;
mysymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
SymFromAddr(process, (DWORD64)((void*)addr), 0, mysymbol);
myprintf("Exit Function: %s [0x%X]\n", mysymbol->Name, addr);
_asm {
popad; // restore regs
mov esp, ebp; // standard epilog
pop ebp;
ret;
}
}
I have been searching around for a while, and couldn't seem to find the answer to my issue. I'm trying to code some functions to detect whether or not the executable is being debugged, and I'm using some inline assembly for it (with the __asm tag). It keeps throwing two errors, and the rest of the code seems to compile fine. Here's the function
int peb_detect() {
__asm {
ASSUME FS : NOTHING
MOV EAX, DWORD PTR FS : [18]
MOV EAX, DBYTE PTR DS : [EAX + 30]
MOVZX EAX, BYTE PTR DS : [EAX + 2]
RET
}
}
and I keep getting the errors
warning C4405: 'FS': identifier is reserved word
warning C2400: inline assembler syntax error in 'opcode'; found 'FS'
warning C2408: illegal type on PTR operator in 'second operand'
I can't seem to figure it out. If anyone can help, I would really appreciate it. Thanks!
at first not 18 but 0x18 and not 30 but 0x30
C_ASSERT(FIELD_OFFSET(NT_TIB, Self) == 0x18);
C_ASSERT(FIELD_OFFSET(TEB, ProcessEnvironmentBlock) == 0x30);
need use not hard coded constants. especially wrong.
at second int peb_detect() must be __declspec(naked) if you use RET instruction. so code can look like this:
#include <winternl.h>
#include <intrin.h>
__declspec(naked) BOOLEAN peb_detect() {
__asm {
MOV EAX, FS:[NT_TIB.Self]
MOV EAX, [EAX + TEB.ProcessEnvironmentBlock]
MOV AL, [EAX + PEB.BeingDebugged]
RET
}
}
but we can use and shorter variant
__declspec(naked) BOOLEAN peb_detect2() {
__asm {
MOV EAX, FS:[TEB.ProcessEnvironmentBlock]
MOV AL, [EAX]PEB.BeingDebugged
RET
}
}
and for implement IsDebuggerPresent we can not use inline assembler at all. and this will be work for x64 too
__forceinline BOOLEAN peb_detect3()
{
return ((PEB*)
#ifdef _WIN64
__readgsqword
#else
__readfsdword
#endif
(FIELD_OFFSET(_TEB, ProcessEnvironmentBlock)))->BeingDebugged;
}
section .text
global start
start:
mov eax, 29
int 80h
ret
I'm pretty sure that pause(void) is syscall 29, so why is this giving me Bus error: 10?
According to sys/syscall.h:
#define SYS_recvfrom 29
I would guess that recvfrom takes some other parameter, giving you the buss error.
If you are actually trying to call pause(void), a cursory examination of source seems to suggest that the definitions are something like the following:
syscalls.h:
#define SYS_sigsuspend 111
sigsuspend.c:
int
sigsuspend (
const sigset_t *sigmask_p
)
{
sigset_t mask;
if (sigmask_p)
mask = *sigmask_p;
else
sigemptyset(&mask);
return syscall (SYS_sigsuspend, mask);
}
sigcompat.c:
int sigpause(mask)
int mask;
{
return (sigsuspend((sigset_t *)&mask));
}
sigpause.c:
int
pause()
{
return sigpause(sigblock(0L));
}
So, while the pause(void) may not take any parameters, the syscall certainly does.
To call pause(void) from assembly, link with libc:
example.asm:
section .text
global start
start:
call pause
ret
Compile with as -o example.o example.asm and link with gcc -static -o a.out example.o
I have assembly code that performs a mathematic equation which result is stored in the ebx register. How can I display the value of the register? I was thinking of pushing the value of ebx to the stack, then "%i\n", and calling printf, but if this would work, I don't know how it could be coded in GCC assembly using MacOS.
#include <stdio.h>
int f()
{
asm("movl $42, %ebx");
asm("movl %ebx, %eax");
}
main() {
printf("%i\n", f()); // displays 42.
}
As you can see, EAX register's content will be used as return value for f() function.