Incompatible function addresses between gcc compiler flags and symbol table

I compiled the project (openssh here, but that doesn't matter) with

CFLAGS="-ggdb3 -O0 -lm -finstrument-functions" 

Character table (small extract):

 nm -o somepath/sbin/sshd /mypath/install/sbin/sshd:000f3548 d auth_method /mypath/install/sbin/sshd:0001a90f t auth_openfile /mypath/install/sbin/sshd:0001ab90 T auth_openkeyfile /mypath/install/sbin/sshd:0001ac31 T auth_openprincipals /mypath/install/sbin/sshd:0001d73a T auth_parse_options /mypath/install/sbin/sshd:0000e362 T auth_password 

What do I get when printing function addresses in __cyg_profile_func_enter|exit :

 0xb768f8ee 0xb768f66c 0xb768f66c 0xb76d9ae8 

Obviously, the same range is not confirmed after viewing all the numbers.

I understand that nm provides offset addresses. How about __cyg_profile_func_enter when there are a lot of files in a project? Is there any additional conversion to perform?

From gcc documentation shouldn't:

  void __cyg_profile_func_enter (void *this_fn, void *call_site); void __cyg_profile_func_exit (void *this_fn, void *call_site); The first argument is the address of the start of the current function, which may be looked up exactly in the symbol table. 

So what am I missing to make it work?

EDIT: my ptrace.c where I added the mutex

 #if (__GNUC__>2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ > 95)) #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <string.h> #include <sys/errno.h> #include <pthread.h> #define PTRACE_PIPENAME "TRACE" #define REFERENCE_OFFSET "REFERENCE:" #define FUNCTION_ENTRY "enter" #define FUNCTION_EXIT "exit" #define END_TRACE "EXIT" #define __NON_INSTRUMENT_FUNCTION__ __attribute__((__no_instrument_function__)) #define PTRACE_OFF __NON_INSTRUMENT_FUNCTION__ #define STR(_x) #_x #define DEF(_x) _x #define GET(_x,_y) _x(_y) #define TRACE __GNU_PTRACE_FILE__ pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; /** Initial trace open */ static FILE *__GNU_PTRACE_FILE__; /** Final trace close */ static void __NON_INSTRUMENT_FUNCTION__ gnu_ptrace_close(void) { fprintf(TRACE, END_TRACE " %ld\n", (long)getpid()); int res = fflush(TRACE); if (res < 0) { printf("Erreur sur gnu_ptrace_close / fflush\n"); } if (TRACE != NULL) fclose(TRACE); pthread_mutex_destroy(&lock); return ; } /** Trace initialization */ static int __NON_INSTRUMENT_FUNCTION__ gnu_ptrace_init(void) { struct stat sta; __GNU_PTRACE_FILE__ = NULL; /* See if a trace file exists */ if (stat(PTRACE_PIPENAME, &sta) != 0) { /* No trace file: do not trace at all */ return 0; } else { /* trace file: open up trace file */ if ((TRACE = fopen(PTRACE_PIPENAME, "a")) == NULL) { char *msg = strerror(errno); perror(msg); printf("[gnu_ptrace error]\n"); return 0; } #ifdef PTRACE_REFERENCE_FUNCTION fprintf(TRACE,"%s %s %p\n", REFERENCE_OFFSET, GET(STR,PTRACE_REFERENCE_FUNCTION), (void *)GET(DEF,PTRACE_REFERENCE_FUNCTION)); #endif /* Tracing requested: a trace file was found */ atexit(gnu_ptrace_close); return 1; } } /** Function called by every function event */ void __NON_INSTRUMENT_FUNCTION__ gnu_ptrace(char * what, void * p) { static int first=1; static int active=1; int res = 0; if (active == 0) return; if (first) { active = gnu_ptrace_init(); first = 0; if (active == 0) return; } if (!what || !p) { printf("Erreur, what ou p NULL\n"); return; } if (strcmp(what, FUNCTION_ENTRY) && strcmp(what, FUNCTION_EXIT)) { printf("Erreur, what incorrect\n"); return; } printf("----------------------- what=%sp=%p\n", what, p); res = fprintf(TRACE, "%s %p\n", what, p); if (res < 0) { printf("Erreur sur gnu_ptrace / fprintf\n"); /* active = 0;*/ } if (res > 0) res = fflush(TRACE); if (res < 0) { printf("Erreur sur gnu_ptrace / fflush\n"); active = 0; } return; } /** According to gcc documentation: called upon function entry */ void __NON_INSTRUMENT_FUNCTION__ __cyg_profile_func_enter(void *this_fn, void *call_site) { pthread_mutex_lock(&lock); gnu_ptrace(FUNCTION_ENTRY, this_fn); (void)call_site; pthread_mutex_unlock(&lock); } /** According to gcc documentation: called upon function exit */ void __NON_INSTRUMENT_FUNCTION__ __cyg_profile_func_exit(void *this_fn, void *call_site) { pthread_mutex_lock(&lock); gnu_ptrace(FUNCTION_EXIT, this_fn); (void)call_site; pthread_mutex_unlock(&lock); } #endif 

Here is a modified ptrace.c with JHiant ideas. I contacted -ldl

 #include <dlfcn.h> 

_

 Dl_info finfo; if (!dladdr(p, &finfo)) printf("Erreur, dladdr\n"); /* res = fprintf(TRACE, "%s %p\n", what, p); */ res = fprintf(TRACE, "%s %p %s (%s)\t\n", what, p, finfo.dli_sname, finfo.dli_fname); 

Here is the resulting trace (first lines):

 enter 0xb7494974 OPENSSL_cpuid_setup (/home/laurent/Documents/projet/install/lib/libcrypto.so.1.0.0) exit 0xb7494974 OPENSSL_cpuid_setup (/home/laurent/Documents/projet/install/lib/libcrypto.so.1.0.0) enter 0xb76ac470 main (/home/laurent/Documents/projet/install/sbin/sshd) enter 0xb76b34fe (null) (/home/laurent/Documents/projet/install/sbin/sshd) exit 0xb76b34fe (null) (/home/laurent/Documents/projet/install/sbin/sshd) enter 0xb7749384 (null) (/home/laurent/Documents/projet/install/sbin/sshd) enter 0xb770496e (null) (/home/laurent/Documents/projet/install/sbin/sshd) enter 0xb77046ec (null) (/home/laurent/Documents/projet/install/sbin/sshd) exit 0xb77046ec (null) (/home/laurent/Documents/projet/install/sbin/sshd) enter 0xb774eb68 (null) (/home/laurent/Documents/projet/install/sbin/sshd) exit 0xb774eb68 (null) (/home/laurent/Documents/projet/install/sbin/sshd) exit 0xb770496e (null) (/home/laurent/Documents/projet/install/sbin/sshd) exit 0xb7749384 (null) (/home/laurent/Documents/projet/install/sbin/sshd) 

Other lines show null all the time instead of the function name. I checked sshd cards, using the right libcrypto library with characters. What is surprising in the above trace is that it shows only one libcrypto call, which looks just like an installation, as that name shows.

OpenSSH compiled with (extracting one line of execution execution in the console - all have the same parameters - normaly without -fpic , but the resulting trace is the same):

 gcc -ggdb3 -O0 -lm -finstrument-functions -ldl -fpic -Wall -Wpointer-arith -Wuninitialized -Wsign-compare -Wformat-security -Wno-pointer-sign -Wno-unused-result -fno-strict-aliasing -D_FORTIFY_SOURCE=2 -ftrapv -fno-builtin-memset -fstack-protector-all -fPIE -I. -I. -I/home/laurent/Documents/projet/install/include -DSSHDIR=\"/home/laurent/Documents/projet/install/etc\" -D_PATH_SSH_PROGRAM=\"/home/laurent/Documents/projet/install/bin/ssh\" -D_PATH_SSH_ASKPASS_DEFAULT=\"/home/laurent/Documents/projet/install/libexec/ssh-askpass\" -D_PATH_SFTP_SERVER=\"/home/laurent/Documents/projet/install/libexec/sftp-server\" -D_PATH_SSH_KEY_SIGN=\"/home/laurent/Documents/projet/install/libexec/ssh-keysign\" -D_PATH_SSH_PKCS11_HELPER=\"/home/laurent/Documents/projet/install/libexec/ssh-pkcs11-helper\" -D_PATH_SSH_PIDDIR=\"/var/run\" -D_PATH_PRIVSEP_CHROOT_DIR=\"/var/empty\" -DHAVE_CONFIG_H -c ssh-keyscan.c 

OpenSSL compiled (extracting one line of execution execution in the console - all have the same parameters):

 gcc -I.. -I../.. -I../modes -I../asn1 -I../evp -I../../include -ggdb3 -O0 -lm -finstrument-functions -ldl -fPIC -DOPENSSL_PIC -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -Wa,--noexecstack -DL_ENDIAN -DTERMIO -fomit-frame-pointer -Wall -DOPENSSL_BN_ASM_PART_WORDS -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DRMD160_ASM -DAES_ASM -DVPAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -c -o cms_lib.o cms_lib.c 

Why are there no more traces in OpenSSL / libcrypto?

Why are there no function names in the trace except "main"?

+5
source share
2 answers

A few ideas:

  • Create helloworld.c and make sure nm for this is in sync with what you see. in your profile. This may be a problem with how sshd is created, not your code.
  • Try adding -fpic to your CFLAGS.
  • Mandatory: just make sure that you compile sshd from the source, and not bind it, because the toolkit function is inserted during the compilation step, not the link step. Otherwise, they would simply print addresses that do not belong to sshd lib, such as the address of main () or some helper functions. You might consider adding functio names to output debugging with:

 #include <dlfcn.h> __cyg_profile_func_enter(void *func, void *site) { DL_info finfo; dladdr(fun, &finfo); fprintf(log, "Entered &s", finfo.dli_sname); } 
+1
source

When downloading and executing an executable file (or shared library), it will be downloaded to an arbitrary address, and the linker moves the addresses of all characters (for example, your functions) relative to the load address of the executable file. These addresses may differ from one run of the executable file to another due to the randomization of the location of the address space . You can think of the addresses displayed by nm as relative addresses (to the download location of the executable file).

To print addresses such as nm, you need to know the load address and subtract it from the address specified in your profiling function. Since I am not familiar with the profiling API you are using, I do not know if there is an API to find the displacement offset.

+1
source

Source: https://habr.com/ru/post/1205957/


All Articles