I am using Stackdumps with Win32, to write all return adresses into my logfile. I match these with a mapfile later on (see my article [Post Mortem Debugging][1]).
EDIT:: Problem solved - see my own answer below.
With Windows x64 i do not find a reliable way to write only the return adresses into the logfile. I tried several ways:
Trial 1: Pointer Arithmetic:
CONTEXT Context;
RtlCaptureContext(&Context);
char *eNextBP = (char *)Context.Rdi;
for(ULONG Frame = 0; eNextBP ; Frame++)
{
char *pBP = eNextBP;
eNextBP = *(char **)pBP; // Next BP in Stack
fprintf(LogFile, "*** %2d called from %016LX (pBP at %016LX)\n", Frame,
(ULONG64)*(char **)(pBP + 8), (ULONG64)pBP);
}
This works fine in the debug version - but it crashes in the release version. The value of Context.Rdi has no usable value there. I did check for differences in the compiler settings (visual Studio 2005). I have not found anything suspicious.
Trial 2: Using StackWalk64
RtlCaptureContext(&Context);
STACKFRAME64 stk;
memset(&stk, 0, sizeof(stk));
stk.AddrPC.Offset = Context.Rip;
stk.AddrPC.Mode = AddrModeFlat;
stk.AddrStack.Offset = Context.Rsp;
stk.AddrStack.Mode = AddrModeFlat;
stk.AddrFrame.Offset = Context.Rbp;
stk.AddrFrame.Mode = AddrModeFlat;
for(ULONG Frame = 0; ; Frame++)
{
BOOL result = StackWalk64(
IMAGE_FILE_MACHINE_AMD64, // __in DWORD MachineType,
GetCurrentProcess(), // __in HANDLE hProcess,
GetCurrentThread(), // __in HANDLE hThread,
&stk, // __inout LP STACKFRAME64 StackFrame,
&Context, // __inout PVOID ContextRecord,
NULL, // __in_opt PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
SymFunctionTableAccess64, // __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
SymGetModuleBase64, // __in_opt PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
NULL // __in_opt PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
);
fprintf(gApplSetup.TraceFile, "*** %2d called from %016LX STACK %016LX FRAME %016LX\n", Frame, (ULONG64)stk.AddrPC.Offset, (ULONG64)stk.AddrStack.Offset, (ULONG64)stk.AddrFrame.Offset);
if(! result)
break;
}
This does not only dump the return addresses, but the WHOLE STACK. I receive about 1000 lines in my log file using this approach. I can use this, but i have to search trough the lines and some data of the stacks happens to be a valid code address.
Trial 3: Using Backtrace
static USHORT (WINAPI
*s_pfnCaptureStackBackTrace)(ULONG, ULONG, PVOID*, PULONG) = 0;
if (s_pfnCaptureStackBackTrace == 0)
{
const HMODULE hNtDll = ::GetModuleHandle("ntdll.dll");
reinterpret_cast<void*&>(s_pfnCaptureStackBackTrace)
= ::GetProcAddress(hNtDll, "RtlCaptureStackBackTrace");
}
PVOID myFrames[128];
s_pfnCaptureStackBackTrace(0, 128, myFrames, NULL);
for(int ndx = 0; ndx < 128; ndx++)
fprintf(gApplSetup.TraceFile, "*** BackTrace %3d %016LX\n", ndx, (ULONG64)myFrames[ndx]);
Results in no usable information.
Has anyone implemented such a stack walk in x64 that does only write out the return adresses in the stack? Ive seen the approaches [StackTrace64][2], [StackWalker][3] and other ones. They either do not compile or they are much too much comlicated. It basically is a simple task!
Sample StackDump64.cpp
#include <Windows.h>
#include <DbgHelp.h>
#include <Winbase.h>
#include <stdio.h>
void WriteStackDump()
{
FILE *myFile = fopen("StackDump64.log", "w+t");
CONTEXT Context;
memset(&Context, 0, sizeof(Context));
RtlCaptureContext(&Context);
RtlCaptureContext(&Context);
STACKFRAME64 stk;
memset(&stk, 0, sizeof(stk));
stk.AddrPC.Offset = Context.Rip;
stk.AddrPC.Mode = AddrModeFlat;
stk.AddrStack.Offset = Context.Rsp;
stk.AddrStack.Mode = AddrModeFlat;
stk.AddrFrame.Offset = Context.Rbp;
stk.AddrFrame.Mode = AddrModeFlat;
for(ULONG Frame = 0; ; Frame++)
{
BOOL result = StackWalk64(
IMAGE_FILE_MACHINE_AMD64, // __in DWORD MachineType,
GetCurrentProcess(), // __in HANDLE hProcess,
GetCurrentThread(), // __in HANDLE hThread,
&stk, // __inout LP STACKFRAME64 StackFrame,
&Context, // __inout PVOID ContextRecord,
NULL, // __in_opt PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
SymFunctionTableAccess64, // __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
SymGetModuleBase64, // __in_opt PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
NULL // __in_opt PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
);
fprintf(myFile, "*** %2d called from %016I64LX STACK %016I64LX AddrReturn %016I64LX\n", Frame, stk.AddrPC.Offset, stk.AddrStack.Offset, stk.AddrReturn.Offset);
if(! result)
break;
}
fclose(myFile);
}
void funcC()
{
WriteStackDump();
}
void funcB()
{
funcC();
}
void funcA()
{
funcB();
}
int main(int argc, char *argv[])
{
funcA();
}
Running this sample results in the follwing log file content:
*** 0 called from 000000014000109E STACK 000000000012F780 AddrReturn 0000000140005798
*** 1 called from 000000001033D160 STACK 000000000012F788 AddrReturn 00000001400057B0
*** 2 called from 00000001400057B0 STACK 000000000012F790 AddrReturn 0000000000000001
*** 3 called from 0000000000000002 STACK 000000000012F798 AddrReturn 00000001400057B0
*** 4 called from 0000000000000002 STACK 000000000012F7A0 AddrReturn 000000000012F7F0
*** 5 called from 000000000012F7F0 STACK 000000000012F7A8 AddrReturn 0000000000000000
*** 6 called from 0000000000000000 STACK 000000000012F7B0 AddrReturn 000007FF7250CF40
*** 7 called from 000007FF7250CF40 STACK 000000000012F7B8 AddrReturn 000007FF7250D390
*** 8 called from 000007FF7250D390 STACK 000000000012F7C0 AddrReturn 000007FF725B6950
*** 9 called from 000007FF725B6950 STACK 000000000012F7C8 AddrReturn CCCCCCCCCCCCCCCC
*** 10 called from CCCCCCCCCCCCCCCC STACK 000000000012F7D0 AddrReturn 000000001033D160
*** 11 called from 000000001033D160 STACK 000000000012F7D8 AddrReturn CCCCCCCCCCCCCCCC
*** 12 called from CCCCCCCCCCCCCCCC STACK 000000000012F7E0 AddrReturn CCCCCCCCCCCCCCCC
*** 13 called from CCCCCCCCCCCCCCCC STACK 000000000012F7E8 AddrReturn CCCCCCCCCCCCCCCC
*** 14 called from CCCCCCCCCCCCCCCC STACK 000000000012F7F0 AddrReturn 0000000000000000
*** 15 called from 0000000000000000 STACK 000000000012F7F8 AddrReturn 0000000000000000
*** 16 called from 0000000000000000 STACK 000000000012F800 AddrReturn 0000000000000000
*** 17 called from 0000000000000000 STACK 000000000012F808 AddrReturn 0000000000000000
*** 18 called from 0000000000000000 STACK 000000000012F810 AddrReturn 0000000000000000
*** 19 called from 0000000000000000 STACK 000000000012F818 AddrReturn 0000000000000000
*** 20 called from 0000000000000000 STACK 000000000012F820 AddrReturn 00001F800010000F
*** 21 called from 00001F800010000F STACK 000000000012F828 AddrReturn 0053002B002B0033
*** 22 called from 0053002B002B0033 STACK 000000000012F830 AddrReturn 00000206002B002B
*** 23 called from 00000206002B002B STACK 000000000012F838 AddrReturn 0000000000000000
*** 24 called from 0000000000000000 STACK 000000000012F840 AddrReturn 0000000000000000
*** 25 called from 0000000000000000 STACK 000000000012F848 AddrReturn 0000000000000000
*** 26 called from 0000000000000000 STACK 000000000012F850 AddrReturn 0000000000000000
*** 27 called from 0000000000000000 STACK 000000000012F858 AddrReturn 0000000000000000
*** 28 called from 0000000000000000 STACK 000000000012F860 AddrReturn 0000000000000000
*** 29 called from 0000000000000000 STACK 000000000012F868 AddrReturn 0000000000000246
*** 30 called from 0000000000000246 STACK 000000000012F870 AddrReturn 000000000012F7F0
*** 31 called from 000000000012F7F0 STACK 000000000012F878 AddrReturn 0000000000000000
*** 32 called from 0000000000000000 STACK 000000000012F880 AddrReturn 0000000000000000
*** 33 called from 0000000000000000 STACK 000000000012F888 AddrReturn 000000000012F888
*** 34 called from 000000000012F888 STACK 000000000012F890 AddrReturn 0000000000000000
*** 35 called from 0000000000000000 STACK 000000000012F898 AddrReturn 0000000000000000
*** 36 called from 0000000000000000 STACK 000000000012F8A0 AddrReturn 000000000012FE10
*** 37 called from 000000000012FE10 STACK 000000000012F8A8 AddrReturn 0000000000000000
*** 38 called from 0000000000000000 STACK 000000000012F8B0 AddrReturn 0000000000000000
*** 39 called from 0000000000000000 STACK 000000000012F8B8 AddrReturn 0000000000000000
*** 40 called from 0000000000000000 STACK 000000000012F8C0 AddrReturn 0000000000000246
*** 41 called from 0000000000000246 STACK 000000000012F8C8 AddrReturn 0000000000000000
*** 42 called from 0000000000000000 STACK 000000000012F8D0 AddrReturn 0000000000000000
*** 43 called from 0000000000000000 STACK 000000000012F8D8 AddrReturn 0000000000000000
*** 44 called from 0000000000000000 STACK 000000000012F8E0 AddrReturn 0000000000000000
*** 45 called from 0000000000000000 STACK 000000000012F8E8 AddrReturn 0000000000000000
*** 46 called from 0000000000000000 STACK 000000000012F8F0 AddrReturn 000000000000027F
*** 47 called from 000000000000027F STACK 000000000012F8F8 AddrReturn 0000000000000000
*** 48 called from 0000000000000000 STACK 000000000012F900 AddrReturn 0000000000000000
*** 49 called from 0000000000000000 STACK 000000000012F908 AddrReturn 0000FFFF00001F80
*** 50 called from 0000FFFF00001F80 STACK 000000000012F910 AddrReturn 0000000000000000
*** 51 called from 0000000000000000 STACK 000000000012F918 AddrReturn 0000000000000000
*** 52 called from 0000000000000000 STACK 000000000012F920 AddrReturn 0000000000000000
*** 53 called from 0000000000000000 STACK 000000000012F928 AddrReturn 0000000000000000
*** 54 called from 0000000000000000 STACK 000000000012F930 AddrReturn 0000000000000000
*** 55 called from 0000000000000000 STACK 000000000012F938 AddrReturn 0000000000000000
*** 56 called from 0000000000000000 STACK 000000000012F940 AddrReturn 0000000000000000
*** 57 called from 0000000000000000 STACK 000000000012F948 AddrReturn 0000000000000000
*** 58 called from 0000000000000000 STACK 000000000012F950 AddrReturn 0000000000000000
*** 59 called from 0000000000000000 STACK 000000000012F958 AddrReturn 0000000000000000
*** 60 called from 0000000000000000 STACK 000000000012F960 AddrReturn 0000000000000000
*** 61 called from 0000000000000000 STACK 000000000012F968 AddrReturn 0000000000000000
*** 62 called from 0000000000000000 STACK 000000000012F970 AddrReturn 0000000000000000
*** 63 called from 0000000000000000 STACK 000000000012F978 AddrReturn 0000000000000000
*** 64 called from 0000000000000000 STACK 000000000012F980 AddrReturn 0000000000000000
*** 65 called from 0000000000000000 STACK 000000000012F988 AddrReturn 0000000000000000
*** 66 called from 0000000000000000 STACK 000000000012F990 AddrReturn 0000000000000000
*** 67 called from 0000000000000000 STACK 000000000012F998 AddrReturn 0000000000000000
*** 68 called from 0000000000000000 STACK 000000000012F9A0 AddrReturn 0000000000000000
*** 69 called from 0000000000000000 STACK 000000000012F9A8 AddrReturn 0000000000000000
*** 70 called from 0000000000000000 STACK 000000000012F9B0 AddrReturn 0000000000000000
*** 71 called from 0000000000000000 STACK 000000000012F9B8 AddrReturn 0000000000000000
*** 72 called from 0000000000000000 STACK 000000000012F9C0 AddrReturn 0000000000000000
*** 73 called from 0000000000000000 STACK 000000000012F9C8 AddrReturn 0000000000000000
*** 74 called from 0000000000000000 STACK 000000000012F9D0 AddrReturn 0000000000000000
*** 75 called from 0000000000000000 STACK 000000000012F9D8 AddrReturn 0000000000000000
*** 76 called from 0000000000000000 STACK 000000000012F9E0 AddrReturn 0000000000000000
*** 77 called from 0000000000000000 STACK 000000000012F9E8 AddrReturn 0000000000000000
*** 78 called from 0000000000000000 STACK 000000000012F9F0 AddrReturn 0000000000000000
*** 79 called from 0000000000000000 STACK 000000000012F9F8 AddrReturn 0000000000000000
*** 80 called from 0000000000000000 STACK 000000000012FA00 AddrReturn 0000000000000000
*** 81 called from 0000000000000000 STACK 000000000012FA08 AddrReturn 0000000000000000
*** 82 called from 0000000000000000 STACK 000000000012FA10 AddrReturn 0000000000000000
*** 83 called from 0000000000000000 STACK 000000000012FA18 AddrReturn 0000000000000000
*** 84 called from 0000000000000000 STACK 000000000012FA20 AddrReturn 0000000000000000
*** 85 called from 0000000000000000 STACK 000000000012FA28 AddrReturn 0000000000000000
*** 86 called from 0000000000000000 STACK 000000000012FA30 AddrReturn 0000000000000000
*** 87 called from 0000000000000000 STACK 000000000012FA38 AddrReturn 0000000000000000
*** 88 called from 0000000000000000 STACK 000000000012FA40 AddrReturn 0000000000000000
*** 89 called from 0000000000000000 STACK 000000000012FA48 AddrReturn 0000000000000000
*** 90 called from 0000000000000000 STACK 000000000012FA50 AddrReturn 0000000000000000
*** 91 called from 0000000000000000 STACK 000000000012FA58 AddrReturn 0000000000000000
*** 92 called from 0000000000000000 STACK 000000000012FA60 AddrReturn 0000000000000000
*** 93 called from 0000000000000000 STACK 000000000012FA68 AddrReturn 0000000000000000
*** 94 called from 0000000000000000 STACK 000000000012FA70 AddrReturn 0000000000000000
*** 95 called from 0000000000000000 STACK 000000000012FA78 AddrReturn 0000000000000000
*** 96 called from 0000000000000000 STACK 000000000012FA80 AddrReturn 0000000000000000
*** 97 called from 0000000000000000 STACK 000000000012FA88 AddrReturn 0000000000000000
*** 98 called from 0000000000000000 STACK 000000000012FA90 AddrReturn 0000000000000000
*** 99 called from 0000000000000000 STACK 000000000012FA98 AddrReturn 0000000000000000
*** 100 called from 0000000000000000 STACK 000000000012FAA0 AddrReturn 0000000000000000
*** 101 called from 0000000000000000 STACK 000000000012FAA8 AddrReturn 0000000000000000
*** 102 called from 0000000000000000 STACK 000000000012FAB0 AddrReturn 0000000000000000
*** 103 called from 0000000000000000 STACK 000000000012FAB8 AddrReturn 0000000000000000
*** 104 called from 0000000000000000 STACK 000000000012FAC0 AddrReturn 0000000000000000
*** 105 called from 0000000000000000 STACK 000000000012FAC8 AddrReturn 0000000000000000
*** 106 called from 0000000000000000 STACK 000000000012FAD0 AddrReturn 0000000000000000
*** 107 called from 0000000000000000 STACK 000000000012FAD8 AddrReturn 0000000000000000
*** 108 called from 0000000000000000 STACK 000000000012FAE0 AddrReturn 0000000000000000
*** 109 called from 0000000000000000 STACK 000000000012FAE8 AddrReturn 0000000000000000
*** 110 called from 0000000000000000 STACK 000000000012FAF0 AddrReturn 0000000000000000
*** 111 called from 0000000000000000 STACK 000000000012FAF8 AddrReturn 0000000000000000
*** 112 called from 0000000000000000 STACK 000000000012FB00 AddrReturn 0000000000000000
*** 113 called from 0000000000000000 STACK 000000000012FB08 AddrReturn 0000000000000000
*** 114 called from 0000000000000000 STACK 000000000012FB10 AddrReturn 0000000000000000
*** 115 called from 0000000000000000 STACK 000000000012FB18 AddrReturn 0000000000000000
*** 116 called from 0000000000000000 STACK 000000000012FB20 AddrReturn 0000000000000000
*** 117 called from 0000000000000000 STACK 000000000012FB28 AddrReturn 0000000000000000
*** 118 called from 0000000000000000 STACK 000000000012FB30 AddrReturn 0000000000000000
*** 119 called from 0000000000000000 STACK 000000000012FB38 AddrReturn 0000000000000000
*** 120 called from 0000000000000000 STACK 000000000012FB40 AddrReturn 0000000000000000
*** 121 called from 0000000000000000 STACK 000000000012FB48 AddrReturn 0000000000000000
*** 122 called from 0000000000000000 STACK 000000000012FB50 AddrReturn 0000000000000000
*** 123 called from 0000000000000000 STACK 000000000012FB58 AddrReturn 0000000000000000
*** 124 called from 0000000000000000 STACK 000000000012FB60 AddrReturn 0000000000000000
*** 125 called from 0000000000000000 STACK 000000000012FB68 AddrReturn 0000000000000000
*** 126 called from 0000000000000000 STACK 000000000012FB70 AddrReturn 0000000000000000
*** 127 called from 0000000000000000 STACK 000000000012FB78 AddrReturn 0000000000000000
*** 128 called from 0000000000000000 STACK 000000000012FB80 AddrReturn 0000000000000000
*** 129 called from 0000000000000000 STACK 000000000012FB88 AddrReturn 0000000000000000
*** 130 called from 0000000000000000 STACK 000000000012FB90 AddrReturn 0000000000000000
*** 131 called from 0000000000000000 STACK 000000000012FB98 AddrReturn 0000000000000000
*** 132 called from 0000000000000000 STACK 000000000012FBA0 AddrReturn 0000000000000000
*** 133 called from 0000000000000000 STACK 000000000012FBA8 AddrReturn 0000000000000000
*** 134 called from 0000000000000000 STACK 000000000012FBB0 AddrReturn 0000000000000000
*** 135 called from 0000000000000000 STACK 000000000012FBB8 AddrReturn 0000000000000000
*** 136 called from 0000000000000000 STACK 000000000012FBC0 AddrReturn 0000000000000000
*** 137 called from 0000000000000000 STACK 000000000012FBC8 AddrReturn 0000000000000000
*** 138 called from 0000000000000000 STACK 000000000012FBD0 AddrReturn 0000000000000000
*** 139 called from 0000000000000000 STACK 000000000012FBD8 AddrReturn 0000000000000000
*** 140 called from 0000000000000000 STACK 000000000012FBE0 AddrReturn 0000000000000000
*** 141 called from 0000000000000000 STACK 000000000012FBE8 AddrReturn 0000000000000000
*** 142 called from 0000000000000000 STACK 000000000012FBF0 AddrReturn 0000000000000000
*** 143 called from 0000000000000000 STACK 000000000012FBF8 AddrReturn 0000000000000000
*** 144 called from 0000000000000000 STACK 000000000012FC00 AddrReturn 0000000000000000
*** 145 called from 0000000000000000 STACK 000000000012FC08 AddrReturn 0000000000000000
*** 146 called from 0000000000000000 STACK 000000000012FC10 AddrReturn 0000000000000000
*** 147 called from 0000000000000000 STACK 000000000012FC18 AddrReturn 0000000000000000
*** 148 called from 0000000000000000 STACK 000000000012FC20 AddrReturn 0000000000000000
*** 149 called from 0000000000000000 STACK 000000000012FC28 AddrReturn 0000000000000000
*** 150 called from 0000000000000000 STACK 000000000012FC30 AddrReturn 0000000000000000
*** 151 called from 0000000000000000 STACK 000000000012FC38 AddrReturn 0000000000000000
*** 152 called from 0000000000000000 STACK 000000000012FC40 AddrReturn 0000000000000000
*** 153 called from 0000000000000000 STACK 000000000012FC48 AddrReturn 0000000000000000
*** 154 called from 0000000000000000 STACK 000000000012FC50 AddrReturn 0000000000000000
*** 155 called from 0000000000000000 STACK 000000000012FC58 AddrReturn 0000000000000000
*** 156 called from 0000000000000000 STACK 000000000012FC60 AddrReturn 0000000000000000
*** 157 called from 0000000000000000 STACK 000000000012FC68 AddrReturn 0000000000000000
*** 158 called from 0000000000000000 STACK 000000000012FC70 AddrReturn 0000000000000000
*** 159 called from 0000000000000000 STACK 000000000012FC78 AddrReturn 0000000000000000
*** 160 called from 0000000000000000 STACK 000000000012FC80 AddrReturn 0000000000000000
*** 161 called from 0000000000000000 STACK 000000000012FC88 AddrReturn 0000000000000000
*** 162 called from 0000000000000000 STACK 000000000012FC90 AddrReturn 0000000000000000
*** 163 called from 0000000000000000 STACK 000000000012FC98 AddrReturn 0000000000000000
*** 164 called from 0000000000000000 STACK 000000000012FCA0 AddrReturn 0000000000000000
*** 165 called from 0000000000000000 STACK 000000000012FCA8 AddrReturn 0000000000000000
*** 166 called from 0000000000000000 STACK 000000000012FCB0 AddrReturn 0000000000000000
*** 167 called from 0000000000000000 STACK 000000000012FCB8 AddrReturn 0000000000000000
*** 168 called from 0000000000000000 STACK 000000000012FCC0 AddrReturn CCCCCCCCCCCCCCCC
*** 169 called from CCCCCCCCCCCCCCCC STACK 000000000012FCC8 AddrReturn CCCCCCCCCCCCCCCC
*** 170 called from CCCCCCCCCCCCCCCC STACK 000000000012FCD0 AddrReturn CCCCCCCCCCCCCCCC
*** 171 called from CCCCCCCCCCCCCCCC STACK 000000000012FCD8 AddrReturn CCCCCCCCCCCCCCCC
*** 172 called from CCCCCCCCCCCCCCCC STACK 000000000012FCE0 AddrReturn CCCCCCCCCCCCCCCC
*** 173 called from CCCCCCCCCCCCCCCC STACK 000000000012FCE8 AddrReturn 0000000300000000
*** 174 called from 0000000300000000 STACK 000000000012FCF0 AddrReturn 0000000300000000
*** 175 called from 0000000300000000 STACK 000000000012FCF8 AddrReturn 0000000300000000
*** 176 called from 0000000300000000 STACK 000000000012FD00 AddrReturn 000000000012FCF0
*** 177 called from 000000000012FCF8 STACK 000000000012FD08 AddrReturn 0000000300000000
*** 178 called from 0000000300000000 STACK 000000000012FD10 AddrReturn 000000000012FD10
*** 179 called from 000000000012FD18 STACK 000000000012FD18 AddrReturn 0000000300000000
*** 180 called from 0000000300000000 STACK 000000000012FD20 AddrReturn 0000000000000000
*** 181 called from 0000000000000000 STACK 000000000012FD28 AddrReturn 0000000000000000
*** 182 called from 0000000000000000 STACK 000000000012FD30 AddrReturn 0000000000000000
*** 183 called from 0000000000000000 STACK 000000000012FD38 AddrReturn 0000000000000000
*** 184 called from 0000000000000000 STACK 000000000012FD40 AddrReturn 0000000000000000
*** 185 called from 0000000100000000 STACK 000000000012FD48 AddrReturn 0000000100000000
*** 186 called from 0000000000000000 STACK 000000000012FD50 AddrReturn 0000000000000000
*** 187 called from 0000000000000000 STACK 000000000012FD58 AddrReturn 0000000100000000
*** 188 called from 0000000100000000 STACK 000000000012FD60 AddrReturn 0000000000000000
*** 189 called from 0000000000000000 STACK 000000000012FD68 AddrReturn 0000000000000000
*** 190 called from 0000000000000000 STACK 000000000012FD70 AddrReturn 0000000000000000
*** 191 called from 0000000000000000 STACK 000000000012FD78 AddrReturn 0000000000000000
*** 192 called from 0000000000000000 STACK 000000000012FD80 AddrReturn 0000000000000000
*** 193 called from 0000000000000000 STACK 000000000012FD88 AddrReturn 0000000000000000
*** 194 called from 0000000000000000 STACK 000000000012FD90 AddrReturn 0000000000000000
*** 195 called from 0000000000000000 STACK 000000000012FD98 AddrReturn 0000000000000000
*** 196 called from 0000000000000000 STACK 000000000012FDA0 AddrReturn 0000000000000000
*** 197 called from 0000000000000000 STACK 000000000012FDA8 AddrReturn 0000000000000000
*** 198 called from 0000000000000000 STACK 000000000012FDB0 AddrReturn 0000000000000000
*** 199 called from 0000000000000000 STACK 000000000012FDB8 AddrReturn 0000000000000000
*** 200 called from 0000000000000000 STACK 000000000012FDC0 AddrReturn 0000000000000000
*** 201 called from 0000000000000000 STACK 000000000012FDC8 AddrReturn 0000000000000000
*** 202 called from 0000000000000000 STACK 000000000012FDD0 AddrReturn 0000000000000000
*** 203 called from 0000000000000000 STACK 000000000012FDD8 AddrReturn 0000000000000000
*** 204 called from 0000000000000000 STACK 000000000012FDE0 AddrReturn 0000000000000000
*** 205 called from 0000000000000000 STACK 000000000012FDE8 AddrReturn CCCCCCCCCCCCCCCC
*** 206 called from CCCCCCCCCCCCCCCC STACK 000000000012FDF0 AddrReturn 000000CECCCCCCCC
*** 207 called from 000000CFCCCCCCCC STACK 000000000012FDF8 AddrReturn CCCCCCCC00000001
*** 208 called from CCCCCCCC00000001 STACK 000000000012FE00 AddrReturn FFFFFFFFFFFFFFFE
*** 209 called from FFFFFFFFFFFFFFFE STACK 000000000012FE08 AddrReturn CCCCCCCCCCCCCCCC
*** 210 called from CCCCCCCCCCCCCCCC STACK 000000000012FE10 AddrReturn 000000000012FE40
*** 211 called from 000000000012FE40 STACK 000000000012FE18 AddrReturn 000000014000122F
*** 212 called from 000000014000122F STACK 000000000012FE20 AddrReturn CCCCCCCCCCCCCCCC
*** 213 called from CCCCCCCCCCCCCCCC STACK 000000000012FE28 AddrReturn CCCCCCCCCCCCCCCC
*** 214 called from CCCCCCCCCCCCCCCC STACK 000000000012FE30 AddrReturn CCCCCCCCCCCCCCCC
*** 215 called from CCCCCCCCCCCCCCCC STACK 000000000012FE38 AddrReturn CCCCCCCCCCCCCCCC
*** 216 called from CCCCCCCCCCCCCCCC STACK 000000000012FE40 AddrReturn 000000000012FE70
*** 217 called from 000000000012FE70 STACK 000000000012FE48 AddrReturn 000000014000125F
*** 218 called from 000000014000125F STACK 000000000012FE50 AddrReturn CCCCCCCCCCCCCCCC
*** 219 called from CCCCCCCCCCCCCCCC STACK 000000000012FE58 AddrReturn CCCCCCCCCCCCCCCC
*** 220 called from CCCCCCCCCCCCCCCC STACK 000000000012FE60 AddrReturn CCCCCCCCCCCCCCCC
*** 221 called from CCCCCCCCCCCCCCCC STACK 000000000012FE68 AddrReturn CCCCCCCCCCCCCCCC
*** 222 called from CCCCCCCCCCCCCCCC STACK 000000000012FE70 AddrReturn 000000000012FEA0
*** 223 called from 000000000012FEA0 STACK 000000000012FE78 AddrReturn 000000014000128F
*** 224 called from 000000014000128F STACK 000000000012FE80 AddrReturn CCCCCCCCCCCCCCCC
*** 225 called from CCCCCCCCCCCCCCCC STACK 000000000012FE88 AddrReturn CCCCCCCCCCCCCCCC
*** 226 called from CCCCCCCCCCCCCCCC STACK 000000000012FE90 AddrReturn CCCCCCCCCCCCCCCC
*** 227 called from CCCCCCCCCCCCCCCC STACK 000000000012FE98 AddrReturn CCCCCCCCCCCCCCCC
*** 228 called from CCCCCCCCCCCCCCCC STACK 000000000012FEA0 AddrReturn 000000000012FED0
*** 229 called from 000000000012FED0 STACK 000000000012FEA8 AddrReturn 00000001400012CB
*** 230 called from 00000001400012CB STACK 000000000012FEB0 AddrReturn CCCCCCCCCCCCCCCC
*** 231 called from CCCCCCCCCCCCCCCC STACK 000000000012FEB8 AddrReturn CCCCCCCCCCCCCCCC
*** 232 called from CCCCCCCCCCCCCCCC STACK 000000000012FEC0 AddrReturn CCCCCCCCCCCCCCCC
*** 233 called from CCCCCCCCCCCCCCCC STACK 000000000012FEC8 AddrReturn CCCCCCCCCCCCCCCC
*** 234 called from CCCCCCCCCCCCCCCC STACK 000000000012FED0 AddrReturn 0000000000000000
*** 235 called from 0000000000000000 STACK 000000000012FED8 AddrReturn 000000014000190C
*** 236 called from 000000014000190C STACK 000000000012FEE0 AddrReturn 0000000100000001
*** 237 called from 0000000100000001 STACK 000000000012FEE8 AddrReturn 0000000000454B50
*** 238 called from 0000000000454B50 STACK 000000000012FEF0 AddrReturn 0000000000000000
*** 23
I finally found a reliable way to log the stack frames in x64, using the Windows function CaptureStackBackTrace(). As I did not want to update my SDK, I call it via GetProcAddress(LoadLibrary());
typedef USHORT (WINAPI *CaptureStackBackTraceType)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
CaptureStackBackTraceType func = (CaptureStackBackTraceType)(GetProcAddress(LoadLibrary("kernel32.dll"), "RtlCaptureStackBackTrace"));
if(func == NULL)
return; // WOE 29.SEP.2010
// Quote from Microsoft Documentation:
// ## Windows Server 2003 and Windows XP:
// ## The sum of the FramesToSkip and FramesToCapture parameters must be less than 63.
const int kMaxCallers = 62;
void* callers[kMaxCallers];
int count = (func)(0, kMaxCallers, callers, NULL);
for(i = 0; i < count; i++)
printf(TraceFile, "*** %d called from %016I64LX\n", i, callers[i]);
For vs2008 x64:
Based on https://msdn.microsoft.com/en-us/library/windows/desktop/bb204633%28v=vs.85%29.aspx and RED SOFT ADAIR:
#if defined DEBUG_SAMPLES_MANAGEMENT
#include "DbgHelp.h"
#include <WinBase.h>
#pragma comment(lib, "Dbghelp.lib")
void printStack( void* sample_address, std::fstream& out )
{
typedef USHORT (WINAPI *CaptureStackBackTraceType)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
CaptureStackBackTraceType func = (CaptureStackBackTraceType)(GetProcAddress(LoadLibrary(L"kernel32.dll"), "RtlCaptureStackBackTrace"));
if(func == NULL)
return; // WOE 29.SEP.2010
// Quote from Microsoft Documentation:
// ## Windows Server 2003 and Windows XP:
// ## The sum of the FramesToSkip and FramesToCapture parameters must be less than 63.
const int kMaxCallers = 62;
void * callers_stack[ kMaxCallers ];
unsigned short frames;
SYMBOL_INFO * symbol;
HANDLE process;
process = GetCurrentProcess();
SymInitialize( process, NULL, TRUE );
frames = (func)( 0, kMaxCallers, callers_stack, NULL );
symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 );
symbol->MaxNameLen = 255;
symbol->SizeOfStruct = sizeof( SYMBOL_INFO );
out << "(" << sample_address << "): " << std::endl;
const unsigned short MAX_CALLERS_SHOWN = 6;
frames = frames < MAX_CALLERS_SHOWN? frames : MAX_CALLERS_SHOWN;
for( unsigned int i = 0; i < frames; i++ )
{
SymFromAddr( process, ( DWORD64 )( callers_stack[ i ] ), 0, symbol );
out << "*** " << i << ": " << callers_stack[i] << " " << symbol->Name << " - 0x" << symbol->Address << std::endl;
}
free( symbol );
}
#endif
Called here:
#if defined DEBUG_SAMPLES_MANAGEMENT
if(owner_ != 0)
{
std::fstream& out = owner_->get_debug_file();
printStack( this, out );
}
#endif
We use minidumps exclusively here. You can generate a stripped down one that just includes stack information and dump out a stack trace from a decent debugger later.
It doesn't solve your problem directly, but I think it will provide you a much better postmortem reporting mechanism.
Disassembling RtlCaptureStackBackTrace() I noticed that maximum value passed to RtlCaptureStackBackTrace() should be: framesToSkip+framesToCapture+1 should be less than 64.
otherwise it returns 0 and there is no other error codes.
In Trial 3, you may be using CaptureStackBackTrace() incorrectly. According to the documentation, on Windows XP and Windows Server 2003, the sum of the first and second parameters must be less than 63, but, in your case, the sum would be 128.
http://msdn.microsoft.com/en-us/library/windows/desktop/bb204633%28v=vs.85%29.aspx
Watch this, I do not know if it is relevant:
...
Working with Assembly Code
Assembly code is straightforward to port to AMD64 and 64-bit Windows—and is worth the effort for performance reasons! For example, you can take advantage of the new 64-bit general-purpose registers (r8-r15), and new floating point and 128-bit SSE/SSE2/floating point registers (xmm8-xmm15). However, there are new 64-bit stack frames and calling conventions you should learn about in the ABI (application binary interface) specifications.
...
The trick is to stop calling StackWalk64 when it returns 0 in stk.AddrReturn.Offset. This means there are no more frames on the stack. If stk.AddrReturn.Offset is non-zero, you can use that value as the return address.
If you continue calling StackWalk64 after this, my guess is that it will try to interpret whatever is in the memory locations as being a stack and will return unpredictable data.
StackWalk64 is the right choice, the first call will give you the caller's address.
Your problem might be that in release you have a lot of inlining going on. The return address may not be what you expect.
edit : you only need to set AddrPC and AddrFrame. Just make sure that your rbp and rip are the ones corresponding to your callee context.
Regarding the first issue: disable "Omit stack frames" in thre release version, and the "trivial" stack tracing code will work.
Regarding RtlCaptureStackBackTrace, one thing I've noticed on 32-bit Windows is that it fails if you pass too large a number into it for FramesToCapture. Experimentally I've identified 61 as the maximum value, for no reason that I can fathom!
Not sure if it's the same in x64, but that might explain why you're getting no info out.
When using StackWalk64 you are iterating through the thread's entire stack whether there is valid data or not. Once you hit a return address of 0 you should terminate the walk, like so:
for (ULONG Frame = 0; ; Frame++)
{
if (FALSE == StackWalk64(...))
{
printf("Stack walk failed!\n");
break;
}
if (stackFrame.AddrPC.Offset == 0)
{
printf("Stack walk complete!\n");
break;
}
do_something();
}
Found the short version with the "CaptureStackBackTraceType" really useful!
Then resolved function names of the "callers[]" using
SymFromAddr(), SymInitialize(),
which is mainly the version from Pedro Reis
and finally demangled the function signatures according to
function to mangle/demangle functions
NOTE: GNU demangler function abi::__cxa_demangle() expects a single underscore prefix
Related
I'm trying to install the code from this git-repo for a university project and I'm stuck because ld does not seem to be able to link lua properly. I followed the install instructions and compile the code with:
catkin_make -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=/usr/bin/python3 -DCMAKE_CXX_STANDARD=14
which fails with several messages like:
/usr/bin/ld: /home/felixk/catkin_ws/devel/lib/libflatland_lib.so: undefined reference to `lua_toboolean(lua_State*, int)'
/usr/bin/ld: /home/felixk/catkin_ws/devel/lib/libflatland_lib.so: undefined reference to `lua_tonumberx(lua_State*, int, int*)'
...
/usr/bin/ld: /home/felixk/catkin_ws/devel/lib/libflatland_lib.so: undefined reference to `lua_pushstring(lua_State*, char const*)'
/usr/bin/ld: /home/felixk/catkin_ws/devel/lib/libflatland_lib.so: undefined reference to `lua_isstring(lua_State*, int)'
collect2: error: ld returned 1 exit status
The code was tested and works on Ubuntu 18.04 but I'm trying to get it to work on Manjaro. The manual states that liblua5.2-dev is needed and I installed lua52 from the AUR which seems to provide the right libraries.
The output of ldd is:
ldd /home/felixk/catkin_ws/devel/lib/libflatland_lib.so | grep lua
liblua5.2.so.5.2 => /usr/lib/liblua5.2.so.5.2 (0x00007f23fd51c000)
Then I checked if /usr/lib/liblua5.2.so.5.2 exists and it does. I tried to use readelf to check whether liblua5.2.so.5.2 contains the undefined references:
readelf -s /usr/lib/liblua5.2.so.5.2
Symbol table '.dynsym' contains 245 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __[...]#GLIBC_2.3 (2)
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND free#GLIBC_2.2.5 (3)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND abort#GLIBC_2.2.5 (3)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND ldexp#GLIBC_2.2.5 (4)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
9: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
10: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
11: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __[...]#GLIBC_2.7 (5)
12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
13: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fread#GLIBC_2.2.5 (3)
14: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND stdin#GLIBC_2.2.5 (3)
15: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
16: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
17: 0000000000000000 0 FUNC GLOBAL DEFAULT UND atan#GLIBC_2.2.5 (4)
18: 0000000000000000 0 FUNC GLOBAL DEFAULT UND pow#GLIBC_2.29 (6)
19: 0000000000000000 0 FUNC GLOBAL DEFAULT UND clock#GLIBC_2.2.5 (3)
20: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
21: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
22: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __[...]#GLIBC_2.4 (7)
23: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
24: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
25: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
26: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
27: 0000000000000000 0 FUNC GLOBAL DEFAULT UND modf#GLIBC_2.2.5 (4)
28: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
29: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
30: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
31: 0000000000000000 0 FUNC GLOBAL DEFAULT UND close#GLIBC_2.2.5 (3)
32: 0000000000000000 0 FUNC GLOBAL DEFAULT UND log#GLIBC_2.29 (6)
33: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fmod#GLIBC_2.2.5 (4)
34: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
35: 0000000000000000 0 FUNC GLOBAL DEFAULT UND cos#GLIBC_2.2.5 (4)
36: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
37: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
38: 0000000000000000 0 FUNC GLOBAL DEFAULT UND acos#GLIBC_2.2.5 (4)
39: 0000000000000000 0 FUNC GLOBAL DEFAULT UND srand#GLIBC_2.2.5 (3)
40: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
41: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fgets#GLIBC_2.2.5 (3)
42: 0000000000000000 0 FUNC GLOBAL DEFAULT UND frexp#GLIBC_2.2.5 (4)
43: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
44: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
45: 0000000000000000 0 FUNC GLOBAL DEFAULT UND log10#GLIBC_2.2.5 (4)
46: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.3.4 (8)
47: 0000000000000000 0 FUNC GLOBAL DEFAULT UND feof#GLIBC_2.2.5 (3)
48: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
49: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
50: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
51: 0000000000000000 0 FUNC GLOBAL DEFAULT UND memcpy#GLIBC_2.14 (9)
52: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
53: 0000000000000000 0 FUNC GLOBAL DEFAULT UND cosh#GLIBC_2.2.5 (4)
54: 0000000000000000 0 FUNC GLOBAL DEFAULT UND time#GLIBC_2.2.5 (3)
55: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (10)
56: 0000000000000000 0 FUNC GLOBAL DEFAULT UND sinh#GLIBC_2.2.5 (4)
57: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
58: 0000000000000000 0 FUNC GLOBAL DEFAULT UND tan#GLIBC_2.2.5 (4)
59: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
60: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
61: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
62: 0000000000000000 0 FUNC GLOBAL DEFAULT UND atan2#GLIBC_2.2.5 (4)
63: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
64: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
65: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
66: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (10)
67: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
68: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
69: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
70: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.11 (11)
71: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
72: 0000000000000000 0 FUNC GLOBAL DEFAULT UND popen#GLIBC_2.2.5 (3)
73: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fopen#GLIBC_2.2.5 (3)
74: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
75: 0000000000000000 0 FUNC GLOBAL DEFAULT UND sin#GLIBC_2.2.5 (4)
76: 0000000000000000 0 FUNC GLOBAL DEFAULT UND tanh#GLIBC_2.2.5 (4)
77: 0000000000000000 0 FUNC GLOBAL DEFAULT UND asin#GLIBC_2.2.5 (4)
78: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit#GLIBC_2.2.5 (3)
79: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
80: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.3.4 (8)
81: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMC[...]
82: 0000000000000000 0 FUNC GLOBAL DEFAULT UND sqrt#GLIBC_2.2.5 (4)
83: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
84: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (10)
85: 0000000000000000 0 FUNC WEAK DEFAULT UND [...]#GLIBC_2.2.5 (3)
86: 0000000000000000 0 FUNC GLOBAL DEFAULT UND getc#GLIBC_2.2.5 (3)
87: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
88: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exp#GLIBC_2.29 (6)
89: 0000000000000000 0 FUNC GLOBAL DEFAULT UND rand#GLIBC_2.2.5 (3)
90: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (10)
91: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __[...]#GLIBC_2.3 (2)
92: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __[...]#GLIBC_2.3 (2)
93: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND [...]#GLIBC_2.2.5 (3)
94: 0000000000000000 0 FUNC GLOBAL DEFAULT UND [...]#GLIBC_2.3.4 (8)
95: 0000000000007680 135 FUNC GLOBAL DEFAULT 9 lua_arith
96: 0000000000008640 32 FUNC GLOBAL DEFAULT 9 lua_getctx
97: 00000000000085d0 97 FUNC GLOBAL DEFAULT 9 lua_setuservalue
98: 0000000000008bd0 24 FUNC GLOBAL DEFAULT 9 lua_getallocf
99: 00000000000086f0 273 FUNC GLOBAL DEFAULT 9 lua_pcallk
100: 0000000000007a80 47 FUNC GLOBAL DEFAULT 9 lua_touserdata
101: 000000000000aff0 1192 FUNC GLOBAL DEFAULT 9 lua_getinfo
102: 000000000001b420 169 FUNC GLOBAL DEFAULT 9 luaL_openlib
103: 0000000000007460 60 FUNC GLOBAL DEFAULT 9 lua_insert
104: 0000000000007580 83 FUNC GLOBAL DEFAULT 9 lua_isnumber
105: 00000000000149d0 231 FUNC GLOBAL DEFAULT 9 lua_newthread
106: 0000000000024d90 117 FUNC GLOBAL DEFAULT 9 luaL_openlibs
107: 000000000001b360 183 FUNC GLOBAL DEFAULT 9 luaL_setfuncs
108: 000000000001ae50 275 FUNC GLOBAL DEFAULT 9 luaL_tolstring
109: 00000000000074a0 30 FUNC GLOBAL DEFAULT 9 lua_replace
110: 000000000001a840 38 FUNC GLOBAL DEFAULT 9 luaL_buffinitsize
111: 0000000000008df0 72 FUNC GLOBAL DEFAULT 9 lua_upvalueid
112: 0000000000007ef0 108 FUNC GLOBAL DEFAULT 9 lua_getglobal
113: 00000000000209c0 42 FUNC GLOBAL DEFAULT 9 luaopen_os
114: 000000000001a870 214 FUNC GLOBAL DEFAULT 9 luaL_ref
115: 000000000000ae00 5 FUNC GLOBAL DEFAULT 9 lua_gethook
116: 0000000000007370 24 FUNC GLOBAL DEFAULT 9 lua_version
117: 0000000000008260 39 FUNC GLOBAL DEFAULT 9 lua_settable
118: 0000000000019b40 159 FUNC GLOBAL DEFAULT 9 luaL_where
119: 000000000001a1f0 63 FUNC GLOBAL DEFAULT 9 luaL_checktype
120: 000000000001a230 58 FUNC GLOBAL DEFAULT 9 luaL_checkany
121: 0000000000019e90 132 FUNC GLOBAL DEFAULT 9 luaL_fileresult
122: 000000000001a5b0 57 FUNC GLOBAL DEFAULT 9 luaL_optunsigned
123: 0000000000008e40 92 FUNC GLOBAL DEFAULT 9 lua_upvaluejoin
124: 000000000001a050 33 FUNC GLOBAL DEFAULT 9 luaL_setmetatable
125: 000000000001a9b0 656 FUNC GLOBAL DEFAULT 9 luaL_loadfilex
126: 0000000000008c00 76 FUNC GLOBAL DEFAULT 9 lua_newuserdata
127: 0000000000007600 26 FUNC GLOBAL DEFAULT 9 lua_isuserdata
128: 000000000001a2c0 106 FUNC GLOBAL DEFAULT 9 luaL_optlstring
129: 000000000001a6f0 44 FUNC GLOBAL DEFAULT 9 luaL_addstring
130: 0000000000007390 34 FUNC GLOBAL DEFAULT 9 lua_absindex
131: 0000000000007c40 98 FUNC GLOBAL DEFAULT 9 lua_pushstring
132: 00000000000078a0 133 FUNC GLOBAL DEFAULT 9 lua_tounsignedx
133: 0000000000008660 135 FUNC GLOBAL DEFAULT 9 lua_callk
134: 0000000000007560 26 FUNC GLOBAL DEFAULT 9 lua_iscfunction
135: 000000000001ad60 85 FUNC GLOBAL DEFAULT 9 luaL_callmeta
136: 000000000001c470 127 FUNC GLOBAL DEFAULT 9 luaopen_base
137: 00000000000250e0 129 OBJECT GLOBAL DEFAULT 11 lua_ident
138: 0000000000008810 219 FUNC GLOBAL DEFAULT 9 lua_load
139: 000000000001acd0 139 FUNC GLOBAL DEFAULT 9 luaL_getmetafield
140: 0000000000007fe0 44 FUNC GLOBAL DEFAULT 9 lua_rawget
141: 00000000000074c0 37 FUNC GLOBAL DEFAULT 9 lua_copy
142: 0000000000008290 94 FUNC GLOBAL DEFAULT 9 lua_setfield
143: 00000000000072e0 102 FUNC GLOBAL DEFAULT 9 lua_xmove
144: 000000000001f430 216 FUNC GLOBAL DEFAULT 9 luaopen_io
145: 0000000000008d10 221 FUNC GLOBAL DEFAULT 9 lua_setupvalue
146: 0000000000019cd0 315 FUNC GLOBAL DEFAULT 9 luaL_argerror
147: 00000000000080c0 102 FUNC GLOBAL DEFAULT 9 lua_createtable
148: 0000000000007350 22 FUNC GLOBAL DEFAULT 9 lua_atpanic
149: 0000000000008010 50 FUNC GLOBAL DEFAULT 9 lua_rawgeti
150: 000000000000c7a0 155 FUNC GLOBAL DEFAULT 9 lua_yieldk
151: 0000000000008b10 145 FUNC GLOBAL DEFAULT 9 lua_concat
152: 000000000001a330 157 FUNC GLOBAL DEFAULT 9 luaL_checkoption
153: 0000000000008050 108 FUNC GLOBAL DEFAULT 9 lua_rawgetp
154: 0000000000008930 391 FUNC GLOBAL DEFAULT 9 lua_gc
155: 00000000000073e0 64 FUNC GLOBAL DEFAULT 9 lua_settop
156: 000000000001b040 127 FUNC GLOBAL DEFAULT 9 luaL_getsubtable
157: 0000000000007dd0 175 FUNC GLOBAL DEFAULT 9 lua_pushcclosure
158: 000000000001ac40 72 FUNC GLOBAL DEFAULT 9 luaL_loadbufferx
159: 0000000000008bf0 12 FUNC GLOBAL DEFAULT 9 lua_setallocf
160: 0000000000007b30 20 FUNC GLOBAL DEFAULT 9 lua_pushnil
161: 0000000000007a50 39 FUNC GLOBAL DEFAULT 9 lua_tocfunction
162: 000000000001a490 109 FUNC GLOBAL DEFAULT 9 luaL_checkinteger
163: 0000000000019f20 175 FUNC GLOBAL DEFAULT 9 luaL_execresult
164: 000000000000ae10 5 FUNC GLOBAL DEFAULT 9 lua_gethookmask
165: 00000000000082f0 126 FUNC GLOBAL DEFAULT 9 lua_rawset
166: 0000000000008920 5 FUNC GLOBAL DEFAULT 9 lua_status
167: 0000000000008ad0 50 FUNC GLOBAL DEFAULT 9 lua_next
168: 000000000001a180 105 FUNC GLOBAL DEFAULT 9 luaL_checkstack
169: 00000000000081e0 119 FUNC GLOBAL DEFAULT 9 lua_setglobal
170: 000000000001a440 67 FUNC GLOBAL DEFAULT 9 luaL_optnumber
171: 0000000000007420 55 FUNC GLOBAL DEFAULT 9 lua_remove
172: 000000000000af50 154 FUNC GLOBAL DEFAULT 9 lua_setlocal
173: 0000000000019fd0 122 FUNC GLOBAL DEFAULT 9 luaL_newmetatable
174: 0000000000014b10 16 FUNC GLOBAL DEFAULT 9 lua_close
175: 000000000000ae20 4 FUNC GLOBAL DEFAULT 9 lua_gethookcount
176: 00000000000077a0 119 FUNC GLOBAL DEFAULT 9 lua_tonumberx
177: 0000000000007cb0 64 FUNC GLOBAL DEFAULT 9 lua_pushvfstring
178: 0000000000007710 143 FUNC GLOBAL DEFAULT 9 lua_compare
179: 0000000000007e80 29 FUNC GLOBAL DEFAULT 9 lua_pushboolean
180: 0000000000007f60 38 FUNC GLOBAL DEFAULT 9 lua_gettable
181: 000000000001ffa0 118 FUNC GLOBAL DEFAULT 9 luaopen_math
182: 0000000000007ba0 53 FUNC GLOBAL DEFAULT 9 lua_pushunsigned
183: 000000000001b0c0 174 FUNC GLOBAL DEFAULT 9 luaL_requiref
184: 000000000000c650 328 FUNC GLOBAL DEFAULT 9 lua_resume
185: 0000000000008370 110 FUNC GLOBAL DEFAULT 9 lua_rawseti
186: 00000000000088f0 41 FUNC GLOBAL DEFAULT 9 lua_dump
187: 000000000001adc0 130 FUNC GLOBAL DEFAULT 9 luaL_len
188: 0000000000022f50 167 FUNC GLOBAL DEFAULT 9 luaopen_string
189: 0000000000007ec0 40 FUNC GLOBAL DEFAULT 9 lua_pushthread
190: 000000000001b170 224 FUNC GLOBAL DEFAULT 9 luaL_gsub
191: 0000000000008c50 181 FUNC GLOBAL DEFAULT 9 lua_getupvalue
192: 00000000000083e0 174 FUNC GLOBAL DEFAULT 9 lua_rawsetp
193: 0000000000007be0 88 FUNC GLOBAL DEFAULT 9 lua_pushlstring
194: 000000000001a720 71 FUNC GLOBAL DEFAULT 9 luaL_pushresult
195: 000000000000adc0 54 FUNC GLOBAL DEFAULT 9 lua_sethook
196: 00000000000075e0 27 FUNC GLOBAL DEFAULT 9 lua_isstring
197: 0000000000019820 800 FUNC GLOBAL DEFAULT 9 luaL_traceback
198: 000000000001a5f0 193 FUNC GLOBAL DEFAULT 9 luaL_prepbuffsize
199: 000000000001a120 85 FUNC GLOBAL DEFAULT 9 luaL_checkudata
200: 0000000000008ac0 9 FUNC GLOBAL DEFAULT 9 lua_error
201: 000000000001a950 83 FUNC GLOBAL DEFAULT 9 luaL_unref
202: 000000000001e150 42 FUNC GLOBAL DEFAULT 9 luaopen_debug
203: 000000000001b280 217 FUNC GLOBAL DEFAULT 9 luaL_checkversion_
204: 000000000001caa0 42 FUNC GLOBAL DEFAULT 9 luaopen_bit32
205: 0000000000007b50 25 FUNC GLOBAL DEFAULT 9 lua_pushnumber
206: 000000000001a780 146 FUNC GLOBAL DEFAULT 9 luaL_addvalue
207: 000000000001a500 107 FUNC GLOBAL DEFAULT 9 luaL_checkunsigned
208: 000000000001a6c0 46 FUNC GLOBAL DEFAULT 9 luaL_addlstring
209: 0000000000007ab0 21 FUNC GLOBAL DEFAULT 9 lua_tothread
210: 000000000001cf50 42 FUNC GLOBAL DEFAULT 9 luaopen_coroutine
211: 0000000000007620 87 FUNC GLOBAL DEFAULT 9 lua_rawequal
212: 00000000000074f0 33 FUNC GLOBAL DEFAULT 9 lua_pushvalue
213: 0000000000008130 105 FUNC GLOBAL DEFAULT 9 lua_getmetatable
214: 0000000000014720 683 FUNC GLOBAL DEFAULT 9 lua_newstate
215: 0000000000007b70 34 FUNC GLOBAL DEFAULT 9 lua_pushinteger
216: 0000000000023b40 79 FUNC GLOBAL DEFAULT 9 luaopen_table
217: 0000000000007f90 79 FUNC GLOBAL DEFAULT 9 lua_getfield
218: 000000000001a570 57 FUNC GLOBAL DEFAULT 9 luaL_optinteger
219: 0000000000019be0 234 FUNC GLOBAL DEFAULT 9 luaL_error
220: 0000000000007930 47 FUNC GLOBAL DEFAULT 9 lua_toboolean
221: 0000000000007ea0 23 FUNC GLOBAL DEFAULT 9 lua_pushlightuserdata
222: 00000000000079e0 111 FUNC GLOBAL DEFAULT 9 lua_rawlen
223: 0000000000007230 162 FUNC GLOBAL DEFAULT 9 lua_checkstack
224: 0000000000007cf0 218 FUNC GLOBAL DEFAULT 9 lua_pushfstring
225: 0000000000008490 317 FUNC GLOBAL DEFAULT 9 lua_setmetatable
226: 0000000000007ad0 96 FUNC GLOBAL DEFAULT 9 lua_topointer
227: 0000000000007540 18 FUNC GLOBAL DEFAULT 9 lua_typename
228: 0000000000007960 128 FUNC GLOBAL DEFAULT 9 lua_tolstring
229: 000000000001a820 28 FUNC GLOBAL DEFAULT 9 luaL_buffinit
230: 000000000001a770 10 FUNC GLOBAL DEFAULT 9 luaL_pushresultsize
231: 000000000001af70 207 FUNC GLOBAL DEFAULT 9 luaL_pushmodule
232: 000000000001b250 47 FUNC GLOBAL DEFAULT 9 luaL_newstate
233: 000000000001a080 148 FUNC GLOBAL DEFAULT 9 luaL_testudata
234: 0000000000007520 30 FUNC GLOBAL DEFAULT 9 lua_type
235: 000000000000ae80 199 FUNC GLOBAL DEFAULT 9 lua_getlocal
236: 000000000001a270 77 FUNC GLOBAL DEFAULT 9 luaL_checklstring
237: 0000000000008bb0 31 FUNC GLOBAL DEFAULT 9 lua_len
238: 000000000000ae30 79 FUNC GLOBAL DEFAULT 9 lua_getstack
239: 000000000001ac90 50 FUNC GLOBAL DEFAULT 9 luaL_loadstring
240: 00000000000081a0 64 FUNC GLOBAL DEFAULT 9 lua_getuservalue
241: 00000000000073c0 23 FUNC GLOBAL DEFAULT 9 lua_gettop
242: 0000000000007820 117 FUNC GLOBAL DEFAULT 9 lua_tointegerx
243: 0000000000024b50 568 FUNC GLOBAL DEFAULT 9 luaopen_package
244: 000000000001a3d0 111 FUNC GLOBAL DEFAULT 9 luaL_checknumber
It seems like all the undefined references exist in /usr/lib/liblua5.2.so.5.2 and I don't know how to go on from here.
Other answers on SO suggest to put the #includes of lua into a extern "C" like so:
extern "C"{
#include <lua5.2/lualib.h>
#include <lua5.2/lauxlib.h>
#include <lua5.2/lua.h>
}
But I would rather not change the given code and wouldn't even know how to find out in which files lua is #included .
Optimally I would only like to change the make command catkin_make -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=/usr/bin/python3 -DCMAKE_CXX_STANDARD=14 to help ld to properly link but I don't know if thats possible. I'm not really familiar with make, cmake or in this case catkin_make and couldn't find out if it is possible to add linker options in the make command.
Lua can be compiled both as C ans C++ languages. This is an advertised feature of it. For that reason, Lua authors decided not to include the classic extern "C" in the headers.
Your liblua5.2.so.5.2 library was compiled in C language and the symbols are not mangled. You compiled your application in C++ mode with just including Lua headers without extern "C", so your Lua included symbols are mangled.
Solution: wrap your include with extern "C":
extern "C"
{
#include "lua.h"
}
The other solution would be to recompile Lua 5.2 as C++ language (with -x c++ compiler option for GCC and Clang, or /TP compiler option for MSVC).
I got it working thanks to prapin's answer :)
I installed lua 5.2 from source following the lua manual.
Instead of prapins suggestion to use the -x c++ compiler option I changed the following in the makefile in lua-5.2.0/src:
changed CC= gcc to CC= g++
added -shared -fPIC to MYCFLAGS= because I needed the .so file.
I hope this helps anybody with this problem who does not want to wrap the includes in extern "C"
i'm a beginner coder here.
so I have a file with main that looks like this
#include <iostream>
#include "Helper.hpp"
using namespace std;
int main(int argc, char* argv[])
{
cout<<argc<<endl;
return 0;
}
and I linked it with 2 other .cpp
I'm just wondering why the executable comes out to be so big (330kb)
when the main doesn't even call any functions.
are all the methods and variables in my other 2 .cpp wrapped up in the executable even though
I haven't actually called any functions? I only have 1 extern int declared. no static functions
this is the makefile call I used to compile
CXX=g++
CXXFLAGS =-Wall -pedantic -g -O0 -std=c++11
test: Helper.cpp Helper.hpp HCTree.cpp HCTree.hpp
$(CXX) $(CXXFLAGS) -o test test.cpp Helper.cpp HCTree.cpp
and I call "make test"
Reason is that your binary will include parts of the standard libraries and the symbol maps, even if you compile the extreme trivial case as follows:
main.cpp
using namespace std;
int main(int argc, char* argv[])
{
return 0;
}
~# g++ -Wall -pedantic -g -O0 -std=c++11 -o test main.cpp
~# ls -ltr
-rwxrwxr-x 1 jordan jordan 10264 Mar 1 08:14 test
after compiling it, my binary is around 10k. If you are compiling it for linux, you can see what is in the binary by calling readelf -a or by examining the symbols in the file with nm.
~# readelf -a test
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: AArch64
Version: 0x1
Entry point address: 0x610
Start of program headers: 64 (bytes into file)
Start of section headers: 8152 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 33
Section header string table index: 32
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000000238 00000238
000000000000001b 0000000000000000 A 0 0 1
[ 2] .note.gnu.build-i NOTE 0000000000000254 00000254
0000000000000024 0000000000000000 A 0 0 4
[ 3] .note.ABI-tag NOTE 0000000000000278 00000278
0000000000000020 0000000000000000 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000000298 00000298
000000000000001c 0000000000000000 A 5 0 8
[ 5] .dynsym DYNSYM 00000000000002b8 000002b8
00000000000000d8 0000000000000018 A 6 3 8
[ 6] .dynstr STRTAB 0000000000000390 00000390
0000000000000082 0000000000000000 A 0 0 1
[ 7] .gnu.version VERSYM 0000000000000412 00000412
0000000000000012 0000000000000002 A 5 0 2
[ 8] .gnu.version_r VERNEED 0000000000000428 00000428
0000000000000020 0000000000000000 A 6 1 8
[ 9] .rela.dyn RELA 0000000000000448 00000448
00000000000000f0 0000000000000018 A 5 0 8
[10] .rela.plt RELA 0000000000000538 00000538
0000000000000060 0000000000000018 AI 5 21 8
[11] .init PROGBITS 0000000000000598 00000598
0000000000000014 0000000000000000 AX 0 0 4
[12] .plt PROGBITS 00000000000005b0 000005b0
0000000000000060 0000000000000010 AX 0 0 16
[13] .text PROGBITS 0000000000000610 00000610
00000000000001ac 0000000000000000 AX 0 0 8
[14] .fini PROGBITS 00000000000007bc 000007bc
0000000000000010 0000000000000000 AX 0 0 4
[15] .rodata PROGBITS 00000000000007cc 000007cc
0000000000000004 0000000000000004 AM 0 0 4
[16] .eh_frame_hdr PROGBITS 00000000000007d0 000007d0
0000000000000044 0000000000000000 A 0 0 4
[17] .eh_frame PROGBITS 0000000000000818 00000818
00000000000000dc 0000000000000000 A 0 0 8
[18] .init_array INIT_ARRAY 0000000000010d88 00000d88
0000000000000008 0000000000000008 WA 0 0 8
[19] .fini_array FINI_ARRAY 0000000000010d90 00000d90
0000000000000008 0000000000000008 WA 0 0 8
[20] .dynamic DYNAMIC 0000000000010d98 00000d98
00000000000001f0 0000000000000010 WA 6 0 8
[21] .got PROGBITS 0000000000010f88 00000f88
0000000000000078 0000000000000008 WA 0 0 8
[22] .data PROGBITS 0000000000011000 00001000
0000000000000010 0000000000000000 WA 0 0 8
[23] .bss NOBITS 0000000000011010 00001010
0000000000000008 0000000000000000 WA 0 0 1
[24] .comment PROGBITS 0000000000000000 00001010
000000000000002a 0000000000000001 MS 0 0 1
[25] .debug_aranges PROGBITS 0000000000000000 0000103a
0000000000000030 0000000000000000 0 0 1
[26] .debug_info PROGBITS 0000000000000000 0000106a
0000000000000098 0000000000000000 0 0 1
[27] .debug_abbrev PROGBITS 0000000000000000 00001102
0000000000000078 0000000000000000 0 0 1
[28] .debug_line PROGBITS 0000000000000000 0000117a
0000000000000050 0000000000000000 0 0 1
[29] .debug_str PROGBITS 0000000000000000 000011ca
00000000000000bf 0000000000000001 MS 0 0 1
[30] .symtab SYMTAB 0000000000000000 00001290
0000000000000900 0000000000000018 31 73 8
[31] .strtab STRTAB 0000000000000000 00001b90
000000000000030d 0000000000000000 0 0 1
[32] .shstrtab STRTAB 0000000000000000 00001e9d
000000000000013a 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040
0x00000000000001f8 0x00000000000001f8 R 0x8
INTERP 0x0000000000000238 0x0000000000000238 0x0000000000000238
0x000000000000001b 0x000000000000001b R 0x1
[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000000008f4 0x00000000000008f4 R E 0x10000
LOAD 0x0000000000000d88 0x0000000000010d88 0x0000000000010d88
0x0000000000000288 0x0000000000000290 RW 0x10000
DYNAMIC 0x0000000000000d98 0x0000000000010d98 0x0000000000010d98
0x00000000000001f0 0x00000000000001f0 RW 0x8
NOTE 0x0000000000000254 0x0000000000000254 0x0000000000000254
0x0000000000000044 0x0000000000000044 R 0x4
GNU_EH_FRAME 0x00000000000007d0 0x00000000000007d0 0x00000000000007d0
0x0000000000000044 0x0000000000000044 R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
GNU_RELRO 0x0000000000000d88 0x0000000000010d88 0x0000000000010d88
0x0000000000000278 0x0000000000000278 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .dynamic .got .data .bss
04 .dynamic
05 .note.gnu.build-id .note.ABI-tag
06 .eh_frame_hdr
07
08 .init_array .fini_array .dynamic .got
Dynamic section at offset 0xd98 contains 27 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000c (INIT) 0x598
0x000000000000000d (FINI) 0x7bc
0x0000000000000019 (INIT_ARRAY) 0x10d88
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x10d90
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x298
0x0000000000000005 (STRTAB) 0x390
0x0000000000000006 (SYMTAB) 0x2b8
0x000000000000000a (STRSZ) 130 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x10f88
0x0000000000000002 (PLTRELSZ) 96 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x538
0x0000000000000007 (RELA) 0x448
0x0000000000000008 (RELASZ) 240 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000000000001e (FLAGS) BIND_NOW
0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
0x000000006ffffffe (VERNEED) 0x428
0x000000006fffffff (VERNEEDNUM) 1
0x000000006ffffff0 (VERSYM) 0x412
0x000000006ffffff9 (RELACOUNT) 6
0x0000000000000000 (NULL) 0x0
Relocation section '.rela.dyn' at offset 0x448 contains 10 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000010d88 000000000403 R_AARCH64_RELATIV 718
000000010d90 000000000403 R_AARCH64_RELATIV 6d0
000000010fc8 000000000403 R_AARCH64_RELATIV 7b8
000000010fe8 000000000403 R_AARCH64_RELATIV 738
000000010ff0 000000000403 R_AARCH64_RELATIV 71c
000000011008 000000000403 R_AARCH64_RELATIV 11008
000000010fd0 000300000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_deregisterTMClone + 0
000000010fd8 000400000401 R_AARCH64_GLOB_DA 0000000000000000 __cxa_finalize#GLIBC_2.17 + 0
000000010fe0 000600000401 R_AARCH64_GLOB_DA 0000000000000000 __gmon_start__ + 0
000000010ff8 000800000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_registerTMCloneTa + 0
Relocation section '.rela.plt' at offset 0x538 contains 4 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000010fa0 000400000402 R_AARCH64_JUMP_SL 0000000000000000 __cxa_finalize#GLIBC_2.17 + 0
000000010fa8 000500000402 R_AARCH64_JUMP_SL 0000000000000000 __libc_start_main#GLIBC_2.17 + 0
000000010fb0 000600000402 R_AARCH64_JUMP_SL 0000000000000000 __gmon_start__ + 0
000000010fb8 000700000402 R_AARCH64_JUMP_SL 0000000000000000 abort#GLIBC_2.17 + 0
The decoding of unwind sections for machine type AArch64 is not currently supported.
Symbol table '.dynsym' contains 9 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000598 0 SECTION LOCAL DEFAULT 11
2: 0000000000011000 0 SECTION LOCAL DEFAULT 22
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
4: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize#GLIBC_2.17 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main#GLIBC_2.17 (2)
6: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND abort#GLIBC_2.17 (2)
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
Symbol table '.symtab' contains 96 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000238 0 SECTION LOCAL DEFAULT 1
2: 0000000000000254 0 SECTION LOCAL DEFAULT 2
3: 0000000000000278 0 SECTION LOCAL DEFAULT 3
4: 0000000000000298 0 SECTION LOCAL DEFAULT 4
5: 00000000000002b8 0 SECTION LOCAL DEFAULT 5
6: 0000000000000390 0 SECTION LOCAL DEFAULT 6
7: 0000000000000412 0 SECTION LOCAL DEFAULT 7
8: 0000000000000428 0 SECTION LOCAL DEFAULT 8
9: 0000000000000448 0 SECTION LOCAL DEFAULT 9
10: 0000000000000538 0 SECTION LOCAL DEFAULT 10
11: 0000000000000598 0 SECTION LOCAL DEFAULT 11
12: 00000000000005b0 0 SECTION LOCAL DEFAULT 12
13: 0000000000000610 0 SECTION LOCAL DEFAULT 13
14: 00000000000007bc 0 SECTION LOCAL DEFAULT 14
15: 00000000000007cc 0 SECTION LOCAL DEFAULT 15
16: 00000000000007d0 0 SECTION LOCAL DEFAULT 16
17: 0000000000000818 0 SECTION LOCAL DEFAULT 17
18: 0000000000010d88 0 SECTION LOCAL DEFAULT 18
19: 0000000000010d90 0 SECTION LOCAL DEFAULT 19
20: 0000000000010d98 0 SECTION LOCAL DEFAULT 20
21: 0000000000010f88 0 SECTION LOCAL DEFAULT 21
22: 0000000000011000 0 SECTION LOCAL DEFAULT 22
23: 0000000000011010 0 SECTION LOCAL DEFAULT 23
24: 0000000000000000 0 SECTION LOCAL DEFAULT 24
25: 0000000000000000 0 SECTION LOCAL DEFAULT 25
26: 0000000000000000 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 SECTION LOCAL DEFAULT 27
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28
29: 0000000000000000 0 SECTION LOCAL DEFAULT 29
30: 0000000000000000 0 FILE LOCAL DEFAULT ABS /usr/lib/gcc/aarch64-linu
31: 0000000000000278 0 NOTYPE LOCAL DEFAULT 3 $d
32: 0000000000000610 0 NOTYPE LOCAL DEFAULT 13 $x
33: 00000000000007cc 0 NOTYPE LOCAL DEFAULT 15 $d
34: 0000000000000000 0 FILE LOCAL DEFAULT ABS /usr/lib/gcc/aarch64-linu
35: 0000000000000648 0 NOTYPE LOCAL DEFAULT 13 $x
36: 0000000000000648 20 FUNC LOCAL DEFAULT 13 call_weak_fn
37: 0000000000000598 0 NOTYPE LOCAL DEFAULT 11 $x
38: 00000000000007bc 0 NOTYPE LOCAL DEFAULT 14 $x
39: 0000000000000000 0 FILE LOCAL DEFAULT ABS /usr/lib/gcc/aarch64-linu
40: 00000000000005a4 0 NOTYPE LOCAL DEFAULT 11 $x
41: 00000000000007c4 0 NOTYPE LOCAL DEFAULT 14 $x
42: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
43: 0000000000000660 0 NOTYPE LOCAL DEFAULT 13 $x
44: 0000000000000660 0 FUNC LOCAL DEFAULT 13 deregister_tm_clones
45: 0000000000000690 0 FUNC LOCAL DEFAULT 13 register_tm_clones
46: 0000000000011008 0 NOTYPE LOCAL DEFAULT 22 $d
47: 00000000000006d0 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
48: 0000000000011010 1 OBJECT LOCAL DEFAULT 23 completed.9126
49: 0000000000010d90 0 NOTYPE LOCAL DEFAULT 19 $d
50: 0000000000010d90 0 OBJECT LOCAL DEFAULT 19 __do_global_dtors_aux_fin
51: 0000000000000718 0 FUNC LOCAL DEFAULT 13 frame_dummy
52: 0000000000010d88 0 NOTYPE LOCAL DEFAULT 18 $d
53: 0000000000010d88 0 OBJECT LOCAL DEFAULT 18 __frame_dummy_init_array_
54: 000000000000082c 0 NOTYPE LOCAL DEFAULT 17 $d
55: 0000000000011010 0 NOTYPE LOCAL DEFAULT 23 $d
56: 0000000000000000 0 FILE LOCAL DEFAULT ABS main.cpp
57: 000000000000071c 0 NOTYPE LOCAL DEFAULT 13 $x
58: 0000000000000890 0 NOTYPE LOCAL DEFAULT 17 $d
59: 0000000000000000 0 FILE LOCAL DEFAULT ABS elf-init.oS
60: 0000000000000738 0 NOTYPE LOCAL DEFAULT 13 $x
61: 00000000000008a8 0 NOTYPE LOCAL DEFAULT 17 $d
62: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
63: 00000000000008f0 0 NOTYPE LOCAL DEFAULT 17 $d
64: 00000000000008f0 0 OBJECT LOCAL DEFAULT 17 __FRAME_END__
65: 0000000000000000 0 FILE LOCAL DEFAULT ABS
66: 0000000000010d90 0 NOTYPE LOCAL DEFAULT 18 __init_array_end
67: 0000000000010d98 0 OBJECT LOCAL DEFAULT ABS _DYNAMIC
68: 0000000000010d88 0 NOTYPE LOCAL DEFAULT 18 __init_array_start
69: 00000000000007d0 0 NOTYPE LOCAL DEFAULT 16 __GNU_EH_FRAME_HDR
70: 0000000000010fc0 0 OBJECT LOCAL DEFAULT ABS _GLOBAL_OFFSET_TABLE_
71: 0000000000000598 0 FUNC LOCAL DEFAULT 11 _init
72: 00000000000005b0 0 NOTYPE LOCAL DEFAULT 12 $x
73: 00000000000007b8 4 FUNC GLOBAL DEFAULT 13 __libc_csu_fini
74: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
75: 0000000000011000 0 NOTYPE WEAK DEFAULT 22 data_start
76: 0000000000011010 0 NOTYPE GLOBAL DEFAULT 23 __bss_start__
77: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize##GLIBC_2.1
78: 0000000000011018 0 NOTYPE GLOBAL DEFAULT 23 _bss_end__
79: 0000000000011010 0 NOTYPE GLOBAL DEFAULT 22 _edata
80: 00000000000007bc 0 FUNC GLOBAL HIDDEN 14 _fini
81: 0000000000011018 0 NOTYPE GLOBAL DEFAULT 23 __bss_end__
82: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main##GLIBC_
83: 0000000000011000 0 NOTYPE GLOBAL DEFAULT 22 __data_start
84: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
85: 0000000000011008 0 OBJECT GLOBAL HIDDEN 22 __dso_handle
86: 0000000000000000 0 FUNC GLOBAL DEFAULT UND abort##GLIBC_2.17
87: 00000000000007cc 4 OBJECT GLOBAL DEFAULT 15 _IO_stdin_used
88: 0000000000000738 124 FUNC GLOBAL DEFAULT 13 __libc_csu_init
89: 0000000000011018 0 NOTYPE GLOBAL DEFAULT 23 _end
90: 0000000000000610 0 FUNC GLOBAL DEFAULT 13 _start
91: 0000000000011018 0 NOTYPE GLOBAL DEFAULT 23 __end__
92: 0000000000011010 0 NOTYPE GLOBAL DEFAULT 23 __bss_start
93: 000000000000071c 24 FUNC GLOBAL DEFAULT 13 main
94: 0000000000011010 0 OBJECT GLOBAL HIDDEN 22 __TMC_END__
95: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
Version symbols section '.gnu.version' contains 9 entries:
Addr: 0x0000000000000412 Offset: 0x000412 Link: 5 (.dynsym)
000: 0 (*local*) 0 (*local*) 0 (*local*) 0 (*local*)
004: 2 (GLIBC_2.17) 2 (GLIBC_2.17) 0 (*local*) 2 (GLIBC_2.17)
008: 0 (*local*)
Version needs section '.gnu.version_r' contains 1 entry:
Addr: 0x0000000000000428 Offset: 0x000428 Link: 6 (.dynstr)
000000: Version: 1 File: libc.so.6 Cnt: 1
0x0010: Name: GLIBC_2.17 Flags: none Version: 2
Displaying notes found in: .note.gnu.build-id
Owner Data size Description
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
Build ID: 3e05092df57e4b081d4823e60f0e74fa226ac79f
Displaying notes found in: .note.ABI-tag
Owner Data size Description
GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
OS: Linux, ABI: 3.7.0
~# nm -a test
nm -a test
0000000000000000 a
U abort##GLIBC_2.17
0000000000011010 b .bss
0000000000011018 B __bss_end__
0000000000011018 B _bss_end__
0000000000011010 B __bss_start
0000000000011010 B __bss_start__
0000000000000648 t call_weak_fn
0000000000000000 n .comment
0000000000011010 b completed.9126
0000000000000000 a crtstuff.c
0000000000000000 a crtstuff.c
w __cxa_finalize##GLIBC_2.17
0000000000011000 d .data
0000000000011000 D __data_start
0000000000011000 W data_start
0000000000000000 N .debug_abbrev
0000000000000000 N .debug_aranges
0000000000000000 N .debug_info
0000000000000000 N .debug_line
0000000000000000 N .debug_str
0000000000000660 t deregister_tm_clones
00000000000006d0 t __do_global_dtors_aux
0000000000010d90 d __do_global_dtors_aux_fini_array_entry
0000000000011008 D __dso_handle
0000000000010d98 d .dynamic
0000000000010d98 a _DYNAMIC
0000000000000390 r .dynstr
00000000000002b8 r .dynsym
0000000000011010 D _edata
0000000000000818 r .eh_frame
00000000000007d0 r .eh_frame_hdr
0000000000000000 a elf-init.oS
0000000000011018 B __end__
0000000000011018 B _end
00000000000007bc t .fini
00000000000007bc T _fini
0000000000010d90 d .fini_array
0000000000000718 t frame_dummy
0000000000010d88 d __frame_dummy_init_array_entry
00000000000008f0 r __FRAME_END__
0000000000010fc0 a _GLOBAL_OFFSET_TABLE_
w __gmon_start__
00000000000007d0 r __GNU_EH_FRAME_HDR
0000000000000298 r .gnu.hash
0000000000000412 r .gnu.version
0000000000000428 r .gnu.version_r
0000000000010f88 d .got
0000000000000598 t .init
0000000000000598 t _init
0000000000010d88 d .init_array
0000000000010d90 d __init_array_end
0000000000010d88 d __init_array_start
0000000000000238 r .interp
00000000000007cc R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
00000000000007b8 T __libc_csu_fini
0000000000000738 T __libc_csu_init
U __libc_start_main##GLIBC_2.17
000000000000071c T main
0000000000000000 a main.cpp
0000000000000278 r .note.ABI-tag
0000000000000254 r .note.gnu.build-id
00000000000005b0 t .plt
0000000000000690 t register_tm_clones
0000000000000448 r .rela.dyn
0000000000000538 r .rela.plt
00000000000007cc r .rodata
0000000000000610 T _start
0000000000000610 t .text
0000000000011010 D __TMC_END__
0000000000000000 a /usr/lib/gcc/aarch64-linux-gnu/9/../../../aarch64-linux-gnu/crti.o
0000000000000000 a /usr/lib/gcc/aarch64-linux-gnu/9/../../../aarch64-linux-gnu/crtn.o
0000000000000000 a /usr/lib/gcc/aarch64-linux-gnu/9/../../../aarch64-linux-gnu/Scrt1.o
You can lower the size by stripping the symbols as follows:
~# strip test
~# ls -ltr
-rwxrwxr-x 1 jordan jordan 6056 Mar 1 08:21 test
so the file went from 10k to 6k.
We have an install application which makes use of MFC and written in c++, It crashes intermittently with the call stack pasted. This crash happens when this application is about to finish. We can see atexit() reference in the call stack with a static variable 'svUniqueUpdates' that is being used inside a function for some computation. Is this crash really caused by atexit() and how to fix it?
Call stack
0 Id: 3f30.8d0 Suspend: 1 Teb: 00000090bbdf7000 Unfrozen
# Child-SP RetAddr : Args to Child : Call Site
00 00000090bc1ffba8 00007ffa7cc507b3 : 0000000000000000 00007ff61fec2370 0000b408eb7e3e32 00007ffa7fa05d78 : Install!TotalUpdCount'::2'::dynamic atexit destructor for 'svUpdates''
01 00000090bc1ffbb0 00007ffa7cc4ce0b : 00000090bc1ffd00 00000090bc1ffc88 00000090bc1ffd20 00007ffa7cd25c80 : ucrtbase!::operator()+0xc3
02 00000090bc1ffc10 00007ffa7cc506e4 : 00000090bc1ffd08 00007ffa7cd25c80 0000000000000000 00000090bc1ffc78 : ucrtbase!__crt_seh_guarded_call::operator()<, & __ptr64, >+0x3b
03 00000090bc1ffc40 00007ffa7cc5bb69 : 00007ffa7cd260a8 00007ffa00000002 0000000000000002 00000090bc1ffc70 : ucrtbase!execute_onexit_table+0x34
04 00000090bc1ffc70 00007ffa7cc4f5ab : 0000000000000001 0000000000000000 000001f7ffffffff 00007ffa684431a8 : ucrtbase!::operator()+0x65
05 00000090bc1ffcb0 00007ffa7cc462ce : 0000000000000001 0000000000000000 0000000000000000 00000090bc1ffd00 : ucrtbase!__crt_seh_guarded_call::operator()<, & __ptr64, >+0x3b
06 00000090bc1ffce0 00007ff61fd110b0 : 0000000000000001 0000000000000000 0000000000000000 0000000000000000 : ucrtbase!common_exit+0x5e
07 00000090bc1ffd30 00007ffa7d628364 : 0000000000000000 0000000000000000 0000000000000000 0000000000000000 : Install!__scrt_common_main_seh+0x16c
08 00000090bc1ffd70 00007ffa7fa0e851 : 0000000000000000 0000000000000000 0000000000000000 0000000000000000 : kernel32!BaseThreadInitThunk+0x14
09 00000090bc1ffda0 0000000000000000 : 0000000000000000 0000000000000000 0000000000000000 0000000000000000 : ntdll!RtlUserThreadStart+0x21
only code using this static variable:
```TotalUpdCount(list<wchar_t *> &lvUpdates)
{
list<wchar_t *>::iterator svListIter;
map<wstring,int>::iterator svVecIter;
static map<wstring,int> svUpdates;
static bool svFirst=true;
if(svFirst)
{
svUpdates.clear();
svFirstTime=false;
}
for (svListIter = lvUpdates.begin();
svListIter != lvUpdates.end();
svListIter++)
{
wstring svTmpUpdate=*svListIter;
svVecIter = svUpdates.find(svTmpUpdate);
if (svVecIter == svUpdates.end())
svUpdates.insert(make_pair(svTmpUpdate, 1));
}
nvTotalUpdatesCnt = static_cast<int>(svUpdates.size());
This question relates specifically to the x86 architecture, g++ compiler and c++ code.
So, I have the following code:
#include <iostream>
int second;
class First {
private:
int hello;
public:
First(int number)
{
hello = number;
}
void printStuff()
{
std::cout<<this->hello<<'\n';
}
};
int main(int argc, char** argv)
{
First *first = new First(argc);
first->printStuff();
second = argc;
return 0;
}
After compiling it like so:
g++ -O0 -g class.cpp -o class
I get the output class binary.
Now, I want to know where hello is stored, so I do readelf -s ./class and the output is:
[ishaypeled#escorpio tmp14]$ readelf -s --wide ./class
Symbol table '.dynsym' contains 13 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSolsEi#GLIBCXX_3.4 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev#GLIBCXX_3.4 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main#GLIBC_2.2.5 (3)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit#GLIBC_2.2.5 (3)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c#GLIBCXX_3.4 (2)
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
10: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _Znwm#GLIBCXX_3.4 (2)
11: 00000000004006c0 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev#GLIBCXX_3.4 (2)
12: 0000000000600dc0 272 OBJECT GLOBAL DEFAULT 26 _ZSt4cout#GLIBCXX_3.4 (2)
Symbol table '.symtab' contains 88 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000400200 0 SECTION LOCAL DEFAULT 1
2: 000000000040021c 0 SECTION LOCAL DEFAULT 2
3: 000000000040023c 0 SECTION LOCAL DEFAULT 3
4: 0000000000400260 0 SECTION LOCAL DEFAULT 4
5: 0000000000400288 0 SECTION LOCAL DEFAULT 5
6: 00000000004003c0 0 SECTION LOCAL DEFAULT 6
7: 0000000000400502 0 SECTION LOCAL DEFAULT 7
8: 0000000000400520 0 SECTION LOCAL DEFAULT 8
9: 0000000000400560 0 SECTION LOCAL DEFAULT 9
10: 0000000000400590 0 SECTION LOCAL DEFAULT 10
11: 0000000000400638 0 SECTION LOCAL DEFAULT 11
12: 0000000000400660 0 SECTION LOCAL DEFAULT 12
13: 00000000004006e0 0 SECTION LOCAL DEFAULT 13
14: 00000000004006f0 0 SECTION LOCAL DEFAULT 14
15: 0000000000400944 0 SECTION LOCAL DEFAULT 15
16: 0000000000400950 0 SECTION LOCAL DEFAULT 16
17: 0000000000400958 0 SECTION LOCAL DEFAULT 17
18: 00000000004009b0 0 SECTION LOCAL DEFAULT 18
19: 0000000000600b30 0 SECTION LOCAL DEFAULT 19
20: 0000000000600b40 0 SECTION LOCAL DEFAULT 20
21: 0000000000600b48 0 SECTION LOCAL DEFAULT 21
22: 0000000000600b50 0 SECTION LOCAL DEFAULT 22
23: 0000000000600d50 0 SECTION LOCAL DEFAULT 23
24: 0000000000600d58 0 SECTION LOCAL DEFAULT 24
25: 0000000000600da8 0 SECTION LOCAL DEFAULT 25
26: 0000000000600dc0 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 SECTION LOCAL DEFAULT 27
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28
29: 0000000000000000 0 SECTION LOCAL DEFAULT 29
30: 0000000000000000 0 SECTION LOCAL DEFAULT 30
31: 0000000000000000 0 SECTION LOCAL DEFAULT 31
32: 0000000000000000 0 SECTION LOCAL DEFAULT 32
33: 0000000000000000 0 SECTION LOCAL DEFAULT 33
34: 0000000000000000 0 FILE LOCAL DEFAULT ABS init.c
35: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
36: 0000000000600b48 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__
37: 0000000000400720 0 FUNC LOCAL DEFAULT 14 deregister_tm_clones
38: 0000000000400760 0 FUNC LOCAL DEFAULT 14 register_tm_clones
39: 00000000004007a0 0 FUNC LOCAL DEFAULT 14 __do_global_dtors_aux
40: 0000000000600ed0 1 OBJECT LOCAL DEFAULT 26 completed.6938
41: 0000000000600b40 0 OBJECT LOCAL DEFAULT 20 __do_global_dtors_aux_fini_array_entry
42: 00000000004007c0 0 FUNC LOCAL DEFAULT 14 frame_dummy
43: 0000000000600b30 0 OBJECT LOCAL DEFAULT 19 __frame_dummy_init_array_entry
44: 0000000000000000 0 FILE LOCAL DEFAULT ABS class.cpp
45: 0000000000400954 1 OBJECT LOCAL DEFAULT 16 _ZStL19piecewise_construct
46: 0000000000600ed8 1 OBJECT LOCAL DEFAULT 26 _ZStL8__ioinit
47: 0000000000400835 62 FUNC LOCAL DEFAULT 14 _Z41__static_initialization_and_destruction_0ii
48: 0000000000400873 21 FUNC LOCAL DEFAULT 14 _GLOBAL__sub_I_second
49: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
50: 0000000000400b28 0 OBJECT LOCAL DEFAULT 18 __FRAME_END__
51: 0000000000600b48 0 OBJECT LOCAL DEFAULT 21 __JCR_END__
52: 0000000000000000 0 FILE LOCAL DEFAULT ABS
53: 0000000000400958 0 NOTYPE LOCAL DEFAULT 17 __GNU_EH_FRAME_HDR
54: 0000000000600d58 0 OBJECT LOCAL DEFAULT 24 _GLOBAL_OFFSET_TABLE_
55: 0000000000600b40 0 NOTYPE LOCAL DEFAULT 19 __init_array_end
56: 0000000000600b30 0 NOTYPE LOCAL DEFAULT 19 __init_array_start
57: 0000000000600b50 0 OBJECT LOCAL DEFAULT 22 _DYNAMIC
58: 0000000000600da8 0 NOTYPE WEAK DEFAULT 25 data_start
59: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSolsEi##GLIBCXX_3.4
60: 0000000000400940 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini
61: 0000000000600ed4 4 OBJECT GLOBAL DEFAULT 26 second
62: 00000000004006f0 42 FUNC GLOBAL DEFAULT 14 _start
63: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
64: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
65: 0000000000400944 0 FUNC GLOBAL DEFAULT 15 _fini
66: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev##GLIBCXX_3.4
67: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main##GLIBC_2.2.5
68: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit##GLIBC_2.2.5
69: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c##GLIBCXX_3.4
70: 00000000004006c0 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev##GLIBCXX_3.4
71: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
72: 0000000000400950 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used
73: 0000000000400888 23 FUNC WEAK DEFAULT 14 _ZN5FirstC1Ei
74: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
75: 0000000000600da8 0 NOTYPE GLOBAL DEFAULT 25 __data_start
76: 00000000004008a0 46 FUNC WEAK DEFAULT 14 _ZN5First10printStuffEv
77: 0000000000400888 23 FUNC WEAK DEFAULT 14 _ZN5FirstC2Ei
78: 0000000000600db8 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__
79: 0000000000600dc0 272 OBJECT GLOBAL DEFAULT 26 _ZSt4cout##GLIBCXX_3.4
80: 0000000000600db0 0 OBJECT GLOBAL HIDDEN 25 __dso_handle
81: 00000000004008d0 101 FUNC GLOBAL DEFAULT 14 __libc_csu_init
82: 0000000000600db8 0 NOTYPE GLOBAL DEFAULT 26 __bss_start
83: 0000000000600ee0 0 NOTYPE GLOBAL DEFAULT 26 _end
84: 0000000000600db8 0 NOTYPE GLOBAL DEFAULT 25 _edata
85: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _Znwm##GLIBCXX_3.4
86: 00000000004007e6 79 FUNC GLOBAL DEFAULT 14 main
87: 0000000000400638 0 FUNC GLOBAL DEFAULT 11 _init
For better readability, I also ran this command:
[ishaypeled#escorpio tmp14]$ readelf -s --wide ./class | c++filt
Symbol table '.dynsym' contains 13 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::basic_ostream<char, std::char_traits<char> >::operator<<(int)#GLIBCXX_3.4 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::Init()#GLIBCXX_3.4 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main#GLIBC_2.2.5 (3)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit#GLIBC_2.2.5 (3)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)#GLIBCXX_3.4 (2)
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
10: 0000000000000000 0 FUNC GLOBAL DEFAULT UND operator new(unsigned long)#GLIBCXX_3.4 (2)
11: 00000000004006c0 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::~Init()#GLIBCXX_3.4 (2)
12: 0000000000600dc0 272 OBJECT GLOBAL DEFAULT 26 std::cout#GLIBCXX_3.4 (2)
Symbol table '.symtab' contains 88 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000400200 0 SECTION LOCAL DEFAULT 1
2: 000000000040021c 0 SECTION LOCAL DEFAULT 2
3: 000000000040023c 0 SECTION LOCAL DEFAULT 3
4: 0000000000400260 0 SECTION LOCAL DEFAULT 4
5: 0000000000400288 0 SECTION LOCAL DEFAULT 5
6: 00000000004003c0 0 SECTION LOCAL DEFAULT 6
7: 0000000000400502 0 SECTION LOCAL DEFAULT 7
8: 0000000000400520 0 SECTION LOCAL DEFAULT 8
9: 0000000000400560 0 SECTION LOCAL DEFAULT 9
10: 0000000000400590 0 SECTION LOCAL DEFAULT 10
11: 0000000000400638 0 SECTION LOCAL DEFAULT 11
12: 0000000000400660 0 SECTION LOCAL DEFAULT 12
13: 00000000004006e0 0 SECTION LOCAL DEFAULT 13
14: 00000000004006f0 0 SECTION LOCAL DEFAULT 14
15: 0000000000400944 0 SECTION LOCAL DEFAULT 15
16: 0000000000400950 0 SECTION LOCAL DEFAULT 16
17: 0000000000400958 0 SECTION LOCAL DEFAULT 17
18: 00000000004009b0 0 SECTION LOCAL DEFAULT 18
19: 0000000000600b30 0 SECTION LOCAL DEFAULT 19
20: 0000000000600b40 0 SECTION LOCAL DEFAULT 20
21: 0000000000600b48 0 SECTION LOCAL DEFAULT 21
22: 0000000000600b50 0 SECTION LOCAL DEFAULT 22
23: 0000000000600d50 0 SECTION LOCAL DEFAULT 23
24: 0000000000600d58 0 SECTION LOCAL DEFAULT 24
25: 0000000000600da8 0 SECTION LOCAL DEFAULT 25
26: 0000000000600dc0 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 SECTION LOCAL DEFAULT 27
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28
29: 0000000000000000 0 SECTION LOCAL DEFAULT 29
30: 0000000000000000 0 SECTION LOCAL DEFAULT 30
31: 0000000000000000 0 SECTION LOCAL DEFAULT 31
32: 0000000000000000 0 SECTION LOCAL DEFAULT 32
33: 0000000000000000 0 SECTION LOCAL DEFAULT 33
34: 0000000000000000 0 FILE LOCAL DEFAULT ABS init.c
35: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
36: 0000000000600b48 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__
37: 0000000000400720 0 FUNC LOCAL DEFAULT 14 deregister_tm_clones
38: 0000000000400760 0 FUNC LOCAL DEFAULT 14 register_tm_clones
39: 00000000004007a0 0 FUNC LOCAL DEFAULT 14 __do_global_dtors_aux
40: 0000000000600ed0 1 OBJECT LOCAL DEFAULT 26 completed.6938
41: 0000000000600b40 0 OBJECT LOCAL DEFAULT 20 __do_global_dtors_aux_fini_array_entry
42: 00000000004007c0 0 FUNC LOCAL DEFAULT 14 frame_dummy
43: 0000000000600b30 0 OBJECT LOCAL DEFAULT 19 __frame_dummy_init_array_entry
44: 0000000000000000 0 FILE LOCAL DEFAULT ABS class.cpp
45: 0000000000400954 1 OBJECT LOCAL DEFAULT 16 std::piecewise_construct
46: 0000000000600ed8 1 OBJECT LOCAL DEFAULT 26 std::__ioinit
47: 0000000000400835 62 FUNC LOCAL DEFAULT 14 __static_initialization_and_destruction_0(int, int)
48: 0000000000400873 21 FUNC LOCAL DEFAULT 14 _GLOBAL__sub_I_second
49: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
50: 0000000000400b28 0 OBJECT LOCAL DEFAULT 18 __FRAME_END__
51: 0000000000600b48 0 OBJECT LOCAL DEFAULT 21 __JCR_END__
52: 0000000000000000 0 FILE LOCAL DEFAULT ABS
53: 0000000000400958 0 NOTYPE LOCAL DEFAULT 17 __GNU_EH_FRAME_HDR
54: 0000000000600d58 0 OBJECT LOCAL DEFAULT 24 _GLOBAL_OFFSET_TABLE_
55: 0000000000600b40 0 NOTYPE LOCAL DEFAULT 19 __init_array_end
56: 0000000000600b30 0 NOTYPE LOCAL DEFAULT 19 __init_array_start
57: 0000000000600b50 0 OBJECT LOCAL DEFAULT 22 _DYNAMIC
58: 0000000000600da8 0 NOTYPE WEAK DEFAULT 25 data_start
59: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::basic_ostream<char, std::char_traits<char> >::operator<<(int)##GLIBCXX_3.4
60: 0000000000400940 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini
61: 0000000000600ed4 4 OBJECT GLOBAL DEFAULT 26 second
62: 00000000004006f0 42 FUNC GLOBAL DEFAULT 14 _start
63: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
64: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
65: 0000000000400944 0 FUNC GLOBAL DEFAULT 15 _fini
66: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::Init()##GLIBCXX_3.4
67: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main##GLIBC_2.2.5
68: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit##GLIBC_2.2.5
69: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)##GLIBCXX_3.4
70: 00000000004006c0 0 FUNC GLOBAL DEFAULT UND std::ios_base::Init::~Init()##GLIBCXX_3.4
71: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
72: 0000000000400950 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used
73: 0000000000400888 23 FUNC WEAK DEFAULT 14 First::First(int)
74: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
75: 0000000000600da8 0 NOTYPE GLOBAL DEFAULT 25 __data_start
76: 00000000004008a0 46 FUNC WEAK DEFAULT 14 First::printStuff()
77: 0000000000400888 23 FUNC WEAK DEFAULT 14 First::First(int)
78: 0000000000600db8 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__
79: 0000000000600dc0 272 OBJECT GLOBAL DEFAULT 26 std::cout##GLIBCXX_3.4
80: 0000000000600db0 0 OBJECT GLOBAL HIDDEN 25 __dso_handle
81: 00000000004008d0 101 FUNC GLOBAL DEFAULT 14 __libc_csu_init
82: 0000000000600db8 0 NOTYPE GLOBAL DEFAULT 26 __bss_start
83: 0000000000600ee0 0 NOTYPE GLOBAL DEFAULT 26 _end
84: 0000000000600db8 0 NOTYPE GLOBAL DEFAULT 25 _edata
85: 0000000000000000 0 FUNC GLOBAL DEFAULT UND operator new(unsigned long)##GLIBCXX_3.4
86: 00000000004007e6 79 FUNC GLOBAL DEFAULT 14 main
87: 0000000000400638 0 FUNC GLOBAL DEFAULT 11 _init
My question is, where is the variable first? I don't see this object in the dump! Note that second is there as symbol 61. I expected mangling of first, but not for it to disappear altogether...
Anyone?
Your object first is just a local object that exists only at the stack. Such objects are not stored in the data section of the executable. The variable second is different because it is global. It is stored with its initial value (default value in your case as you do not explicitly instantiate it) and is defined as a symbol.
example.cpp:
class Clazz {
int x; // will live wherever the instance of Clazz is created
public:
Clazz(const std::initializer_list<int> & data) {}
Clazz() : x(13) {} // "13" is either in constructor code, or .rodata
};
// these will end in .data section
// except the list parameter {1, 2, 3}, which is const and lands in .rodata
static int localInt; // local symbol, will be in .o file only in debug info
int globalInt; // global symbol
// btw, both are initialized to 0, as they are defined in .data
static Clazz *classPtr = nullptr;
Clazz classInstance( {1, 2, 3} );
// all global symbols from .data/.rodata/.bss/.text (.code) sections
// will be visible in symbol table of executable (including the "foo" below)
// everything else defined below (except foo) is runtime allocated,
// and can't have any fixed address in symbol table, so it will not show there.
void foo(int param) { // param is either on stack or in register (ABI specific)
Clazz localVar; // localVar instance is living on the stack space
classPtr = new Clazz({});
// Instance of Clazz pointed at by classPtr lives in global heap memory
// If not released by explicit "delete classPtr;" during runtime,
// it will cause memory leak (avoid using naked pointers like this).
int localInt; // localInt lives on stack too, uninitialized = undefined value!
// On the contrary to *classPtr the localVar is released upon exiting it's scope
}
Neither stack or heap instances are in ELF file, in ELF file is only code capable to manipulate the instance, and to create the instance (either on stack or on heap, either by instancing it as global/local variable, or by new).
So unless you instantiate some type into .data/.bss sections (ie. defining it outside of function, as a global/local of that .cpp file), you can't figure out the where the variable will be kept by looking at symbol table of executable.
I think that in order to understand the output of readelf, we firstly need to understand a little bit of how a compiler works.
basically a compiler takes a C/C++ file as an output and generates an executable file each C/C++ is usually built of functions and variables.
In order to understand this a little bit further we also need to talk about things called "scopes" a scope is basically the place of recognition within the code -
Where within our code the object / functions that we have defined are recognized and accessible.
for example let's take this code
#include <stdio.h>
int myGlob = 5;
int foo()
{
int a = 5;
printf("Hey this is foo -> %d\n",a + 1);
return a + 1;
}
int goo()
{
int b = 5;
printf("Hey this is goo -> %d\n",b - 1);
return b - 1;
}
int main()
{
printf("glob(%d) foo(%d) goo(%d)",myGlob,foo() - 1, goo() +1 );
return 0;
}
we have three functions and one global var
foo -> which has the local variable a within it
goo -> which has the local variable b within it
main -> which has no local variable within it
also we have myGlob which is a global variable
variable a is only accessible within it foo, variable b which is only accessible within the goo function and myGlob which is accessible within all functions but only, so the scope of a is foo the scope of bis goo and the scope of myGlob is the entire model, pretty basic right? this is where we'll get a little bit deeper within the explanation.
each of these functions / GLOBAL objects are called symbols, when writing actual code you have many models and many header files calling and including each other. the compiler compiles one file at a time and outputs an according object file for each compiled model, in order to allow models to recognize other models, upon every model we include something called a symbol table which is basically the collection of all functions and global variables within your code that should be accessible by other models.
e.g:
we have model.h that defines the function foo
we have model.c that implements foo
we have othermodel.c that includes model.h defines and implements
the function foo that calls goo
now if we actually create something like this and run the readelf upon it we would see that model.h + model .c would combine to model.o and othermodel.c would generate othermodel.o, model.o would have within it the symbol foo and the implementation of foo (actual code and instructions) and othermodel.o would have the symbol goo and foo yet only the implementation
of foo
this is where the linker kicks in, when the linker needs to combine all object files into an executable, it reads which object file needs which symbols within it and combines all the files into one executable eventually, again I remind you that symbols may also be functions and global variables.
now that we have a little bit more understanding of what symbols are and why every symbol is used when multiple model scopes are combined we can understand why a local variable shouldn't have it's own symbol
let's go back to our previous example, within the function foo of model.o
there is some local variable b as we've spoken earlier b is only accessible by foo, why on earth would the object file of model.o need to generate a symbol for b? no one other but code within foo can access that variable, so why do the need to recognize or even know about it's existence?
now honestly that's sort of abuse of what actually happens, in real life, local variables are saved on a stack, within your instruction code, when entering some function your memory stack is manually manipulated in order to create some memory buffer to hold all your local variables and data that is regarding the function executing... that so called buffer is called a stack frame, and the beauty of that is once your function is exited, the stack is cleaned, and over functions re-use that memory and run the stack memory with their local variables and function meta data (return addresses for example) unlike local variables, global variables such as myGlob in my example or second in yours are saved in a global memory section that is accessible by all appropriate functions (in reality not always true but for now let's keep it simple), and that memory's life time is throughout the entire program, it doesn't get rewritten constantly like the stack memory and everyone can access it, therefore local variables do not have a need for a symbol or the life-time of an entire program.
if you did not know, classes / structs in C++/C are just a bunch of variables of different type sitting in sequence within memory, if your class instance is local, it's just a bunch of local variables sitting one after the other in the stack memory that the compiler allows you to access with some comfortable name that would be eventually translated to an offset, therefore as we've shown earlier in my long long explanation that you simply shouldn't \ won't have a symbol for a local variable.. if you would like to see a symbol for hello you could've done something such as
static int hello;
which perhaps doesn't give you a global scope accessibility yet gives your variable a lifetime of throughout the program..
anyways hope I've cleared you up somethings, sorry for my poor English skills :)
EDIT:
By the way, this is absolutely has nothing to do with your CPU architecture, even if you compile code for C++ PowerPC, MIPS or ARM, it would stay the same, the only thing that would differentiate is the actual instructions and perhaps the addresses of functions, yet this is more of a concept than it is relevant to CPU architecture
in this code you print just the count of arguments , argc is the number of arguments includes the command , and argv is the the string array which is the words after command seperated by space
a ELF file contains debug info, then the types of variables, structures, and great many other kinds of info can be extracted from that binary.Theoretically possible, but I don't know how to program the implementation under Windows
I have been using Anthony Shoumikhin's elfhook utility to redirect certain function calls in a shared library.
As a proof of concept, I've created a shared library which calls various functions from the posix socket api.
void TestAPI::work()
{
int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
char buf[1024];
recv(fd, buf, sizeof(buf), 0);
listen(fd, 1);
}
I've then hooked these functions:
elf_hook(filename, base_address, "socket", hook_socket);
elf_hook(filename, base_address, "listen", hook_listen);
elf_hook(filename, base_address, "recv", hook_recv);
where a hooked function calls the original api function, but also logs what is happening, for example:
int hook_socket(int domain, int type, int protocol)
{
int fd = socket(domain, type, protocol);
printf("fd=%d domain=%d type=%d protocol=%d\n", fd, domain, type, protocol);
return fd;
}
This all works fine, until I attempt to hook a function which isn't called in my TestAPI shared library
elf_hook(filename, base_address, "bind", hook_bind);
elf_hook(filename, base_address, "connect", hook_connect);
As soon as I do this, I get a segmentation fault:
#0 elf_machine_fixup_plt (map=<optimized out>, t=<optimized out>, reloc=<optimized out>, value=139753823227104, reloc_addr=0x7f1afa15e188) at ../sysdeps/x86_64/dl-machine.h:235
#1 _dl_fixup (l=<optimized out>, reloc_arg=<optimized out>) at ../elf/dl-runtime.c:148
#2 0x00007f1afa176753 in _dl_runtime_resolve_avx () at ../sysdeps/x86_64/dl-trampoline.h:112
#3 0x0000000000561b20 in ?? ()
#4 0x00007f1afa16f8e0 in ?? () at dl-fini.c:105 from /lib64/ld-linux-x86-64.so.2
#5 0x00007f1afa16f5fb in call_init (env=0x7ffff0e3aae0, argv=0x4a7390 <_start>, argc=-253515440, l=<optimized out>) at dl-init.c:30
#6 _dl_init (main_map=0x0, argc=-253515440, argv=0x4a7390 <_start>, env=0x7ffff0e3aae0) at dl-init.c:120
#7 0x000000000000001c in ?? ()
#8 0x0000000000000001 in ?? ()
#9 0x00007ffff0e3c21f in ?? ()
#10 0x0000000000000000 in ?? ()
I've tested this by hooking a function, running my application, seeing it segfault, calling that function in my shared library, running again, and seeing work correctly.
My knowledge of libdl and elf is not up to scratch to know what is happening here or how to prevent it / catch the fact that I've tried to hook a function which doesn't get called.
How can I prevent this from happening?
Edit:
Per request, here is the output of readelf:
$ readelf -s -S --dyn-syms -r ./libtest_api.so
There are 36 section headers, starting at offset 0x14a208:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .note.gnu.build-i NOTE 00000000000001c8 000001c8
0000000000000024 0000000000000000 A 0 0 4
[ 2] .gnu.hash GNU_HASH 00000000000001f0 000001f0
0000000000000044 0000000000000000 A 3 0 8
[ 3] .dynsym DYNSYM 0000000000000238 00000238
0000000000000240 0000000000000018 A 4 2 8
[ 4] .dynstr STRTAB 0000000000000478 00000478
00000000000001b4 0000000000000000 A 0 0 1
[ 5] .gnu.version VERSYM 000000000000062c 0000062c
0000000000000030 0000000000000002 A 3 0 2
[ 6] .gnu.version_r VERNEED 0000000000000660 00000660
0000000000000070 0000000000000000 A 4 3 8
[ 7] .rela.dyn RELA 00000000000006d0 000006d0
00000000000000f0 0000000000000018 A 3 0 8
[ 8] .rela.plt RELA 00000000000007c0 000007c0
00000000000000d8 0000000000000018 AI 3 22 8
[ 9] .init PROGBITS 0000000000000898 00000898
000000000000001a 0000000000000000 AX 0 0 4
[10] .plt PROGBITS 00000000000008c0 000008c0
00000000000000a0 0000000000000010 AX 0 0 16
[11] .plt.got PROGBITS 0000000000000960 00000960
0000000000000010 0000000000000000 AX 0 0 8
[12] .text PROGBITS 0000000000000970 00000970
0000000000000253 0000000000000000 AX 0 0 16
[13] .fini PROGBITS 0000000000000bc4 00000bc4
0000000000000009 0000000000000000 AX 0 0 4
[14] .rodata PROGBITS 0000000000000bd0 00000bd0
0000000000000105 0000000000000000 A 0 0 8
[15] .eh_frame_hdr PROGBITS 0000000000000cd8 00000cd8
0000000000000034 0000000000000000 A 0 0 4
[16] .eh_frame PROGBITS 0000000000000d10 00000d10
00000000000000cc 0000000000000000 A 0 0 8
[17] .init_array INIT_ARRAY 0000000000201dc0 00001dc0
0000000000000010 0000000000000000 WA 0 0 8
[18] .fini_array FINI_ARRAY 0000000000201dd0 00001dd0
0000000000000008 0000000000000000 WA 0 0 8
[19] .jcr PROGBITS 0000000000201dd8 00001dd8
0000000000000008 0000000000000000 WA 0 0 8
[20] .dynamic DYNAMIC 0000000000201de0 00001de0
00000000000001f0 0000000000000010 WA 4 0 8
[21] .got PROGBITS 0000000000201fd0 00001fd0
0000000000000030 0000000000000008 WA 0 0 8
[22] .got.plt PROGBITS 0000000000202000 00002000
0000000000000060 0000000000000008 WA 0 0 8
[23] .data PROGBITS 0000000000202060 00002060
0000000000000008 0000000000000000 WA 0 0 8
[24] .bss NOBITS 0000000000202068 00002068
0000000000000008 0000000000000000 WA 0 0 1
[25] .comment PROGBITS 0000000000000000 00002068
0000000000000034 0000000000000001 MS 0 0 1
[26] .debug_aranges PROGBITS 0000000000000000 0000209c
0000000000000040 0000000000000000 0 0 1
[27] .debug_info PROGBITS 0000000000000000 000020dc
0000000000007a3b 0000000000000000 0 0 1
[28] .debug_abbrev PROGBITS 0000000000000000 00009b17
00000000000009e1 0000000000000000 0 0 1
[29] .debug_line PROGBITS 0000000000000000 0000a4f8
00000000000052dd 0000000000000000 0 0 1
[30] .debug_str PROGBITS 0000000000000000 0000f7d5
000000000011cb84 0000000000000001 MS 0 0 1
[31] .debug_ranges PROGBITS 0000000000000000 0012c359
0000000000000030 0000000000000000 0 0 1
[32] .debug_macro PROGBITS 0000000000000000 0012c389
000000000001c8a8 0000000000000000 0 0 1
[33] .shstrtab STRTAB 0000000000000000 0014a0b4
0000000000000151 0000000000000000 0 0 1
[34] .symtab SYMTAB 0000000000000000 00148c38
0000000000000ba0 0000000000000018 35 102 8
[35] .strtab STRTAB 0000000000000000 001497d8
00000000000008dc 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
Relocation section '.rela.dyn' at offset 0x6d0 contains 10 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000201dc0 000000000008 R_X86_64_RELATIVE a40
000000201dc8 000000000008 R_X86_64_RELATIVE ba2
000000201dd0 000000000008 R_X86_64_RELATIVE a00
000000202060 000000000008 R_X86_64_RELATIVE 202060
000000201fd0 000200000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000201fd8 000300000006 R_X86_64_GLOB_DAT 0000000000000000 _Jv_RegisterClasses + 0
000000201fe0 000800000006 R_X86_64_GLOB_DAT 0000000000000000 _ZNSt8ios_base4InitD1E#GLIBCXX_3.4 + 0
000000201fe8 000900000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTMClone + 0
000000201ff0 000a00000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCloneTa + 0
000000201ff8 000c00000006 R_X86_64_GLOB_DAT 0000000000000000 __cxa_finalize#GLIBC_2.2.5 + 0
Relocation section '.rela.plt' at offset 0x7c0 contains 9 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000202018 000400000007 R_X86_64_JUMP_SLO 0000000000000000 puts#GLIBC_2.2.5 + 0
000000202020 000500000007 R_X86_64_JUMP_SLO 0000000000000000 _ZNSt8ios_base4InitC1E#GLIBCXX_3.4 + 0
000000202028 001600000007 R_X86_64_JUMP_SLO 0000000000000bb8 _ZN5boost6none_tC1ENS0 + 0
000000202030 000600000007 R_X86_64_JUMP_SLO 0000000000000000 recv#GLIBC_2.2.5 + 0
000000202038 000700000007 R_X86_64_JUMP_SLO 0000000000000000 __cxa_atexit#GLIBC_2.2.5 + 0
000000202040 000b00000007 R_X86_64_JUMP_SLO 0000000000000000 listen#GLIBC_2.2.5 + 0
000000202048 000d00000007 R_X86_64_JUMP_SLO 0000000000000000 socket#GLIBC_2.2.5 + 0
000000202050 000e00000007 R_X86_64_JUMP_SLO 0000000000000000 __stack_chk_fail#GLIBC_2.4 + 0
000000202058 000f00000007 R_X86_64_JUMP_SLO 0000000000000000 send#GLIBC_2.2.5 + 0
Symbol table '.dynsym' contains 24 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000898 0 SECTION LOCAL DEFAULT 9
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts#GLIBC_2.2.5 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev#GLIBCXX_3.4 (3)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND recv#GLIBC_2.2.5 (4)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit#GLIBC_2.2.5 (2)
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev#GLIBCXX_3.4 (3)
9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
11: 0000000000000000 0 FUNC GLOBAL DEFAULT UND listen#GLIBC_2.2.5 (2)
12: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize#GLIBC_2.2.5 (2)
13: 0000000000000000 0 FUNC GLOBAL DEFAULT UND socket#GLIBC_2.2.5 (2)
14: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail#GLIBC_2.4 (5)
15: 0000000000000000 0 FUNC GLOBAL DEFAULT UND send#GLIBC_2.2.5 (4)
16: 0000000000202070 0 NOTYPE GLOBAL DEFAULT 24 _end
17: 0000000000202068 0 NOTYPE GLOBAL DEFAULT 23 _edata
18: 0000000000000a70 172 FUNC GLOBAL DEFAULT 12 _ZN10ElfHookAPI4workEv
19: 0000000000202068 0 NOTYPE GLOBAL DEFAULT 24 __bss_start
20: 0000000000000898 0 FUNC GLOBAL DEFAULT 9 _init
21: 0000000000000bc4 0 FUNC GLOBAL DEFAULT 13 _fini
22: 0000000000000bb8 11 FUNC WEAK DEFAULT 12 _ZN5boost6none_tC1ENS0_8i
23: 0000000000000bb8 11 FUNC WEAK DEFAULT 12 _ZN5boost6none_tC2ENS0_8i
Symbol table '.symtab' contains 124 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000000001c8 0 SECTION LOCAL DEFAULT 1
2: 00000000000001f0 0 SECTION LOCAL DEFAULT 2
3: 0000000000000238 0 SECTION LOCAL DEFAULT 3
4: 0000000000000478 0 SECTION LOCAL DEFAULT 4
5: 000000000000062c 0 SECTION LOCAL DEFAULT 5
6: 0000000000000660 0 SECTION LOCAL DEFAULT 6
7: 00000000000006d0 0 SECTION LOCAL DEFAULT 7
8: 00000000000007c0 0 SECTION LOCAL DEFAULT 8
9: 0000000000000898 0 SECTION LOCAL DEFAULT 9
10: 00000000000008c0 0 SECTION LOCAL DEFAULT 10
11: 0000000000000960 0 SECTION LOCAL DEFAULT 11
12: 0000000000000970 0 SECTION LOCAL DEFAULT 12
13: 0000000000000bc4 0 SECTION LOCAL DEFAULT 13
14: 0000000000000bd0 0 SECTION LOCAL DEFAULT 14
15: 0000000000000cd8 0 SECTION LOCAL DEFAULT 15
16: 0000000000000d10 0 SECTION LOCAL DEFAULT 16
17: 0000000000201dc0 0 SECTION LOCAL DEFAULT 17
18: 0000000000201dd0 0 SECTION LOCAL DEFAULT 18
19: 0000000000201dd8 0 SECTION LOCAL DEFAULT 19
20: 0000000000201de0 0 SECTION LOCAL DEFAULT 20
21: 0000000000201fd0 0 SECTION LOCAL DEFAULT 21
22: 0000000000202000 0 SECTION LOCAL DEFAULT 22
23: 0000000000202060 0 SECTION LOCAL DEFAULT 23
24: 0000000000202068 0 SECTION LOCAL DEFAULT 24
25: 0000000000000000 0 SECTION LOCAL DEFAULT 25
26: 0000000000000000 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 SECTION LOCAL DEFAULT 27
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28
29: 0000000000000000 0 SECTION LOCAL DEFAULT 29
30: 0000000000000000 0 SECTION LOCAL DEFAULT 30
31: 0000000000000000 0 SECTION LOCAL DEFAULT 31
32: 0000000000000000 0 SECTION LOCAL DEFAULT 32
33: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
34: 0000000000201dd8 0 OBJECT LOCAL DEFAULT 19 __JCR_LIST__
35: 0000000000000970 0 FUNC LOCAL DEFAULT 12 deregister_tm_clones
36: 00000000000009b0 0 FUNC LOCAL DEFAULT 12 register_tm_clones
37: 0000000000000a00 0 FUNC LOCAL DEFAULT 12 __do_global_dtors_aux
38: 0000000000202068 1 OBJECT LOCAL DEFAULT 24 completed.7585
39: 0000000000201dd0 0 OBJECT LOCAL DEFAULT 18 __do_global_dtors_aux_fin
40: 0000000000000a40 0 FUNC LOCAL DEFAULT 12 frame_dummy
41: 0000000000201dc0 0 OBJECT LOCAL DEFAULT 17 __frame_dummy_init_array_
42: 0000000000000000 0 FILE LOCAL DEFAULT ABS lib_elfhook.cpp
43: 0000000000000bd0 1 OBJECT LOCAL DEFAULT 14 _ZStL19piecewise_construc
44: 0000000000202069 1 OBJECT LOCAL DEFAULT 24 _ZStL8__ioinit
45: 0000000000000bd1 1 OBJECT LOCAL DEFAULT 14 _ZStL13allocator_arg
46: 0000000000000bd2 1 OBJECT LOCAL DEFAULT 14 _ZStL6ignore
47: 0000000000000bd3 1 OBJECT LOCAL DEFAULT 14 _ZStL10defer_lock
48: 0000000000000bd4 1 OBJECT LOCAL DEFAULT 14 _ZStL11try_to_lock
49: 0000000000000bd5 1 OBJECT LOCAL DEFAULT 14 _ZStL10adopt_lock
50: 0000000000000bd8 4 OBJECT LOCAL DEFAULT 14 _ZN9__gnu_cxxL21__default
51: 0000000000000bdc 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobuf8inter
52: 0000000000000be0 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobuf8inter
53: 0000000000000be4 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL9kint
54: 0000000000000be8 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL9kint
55: 0000000000000bf0 8 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL9kint
56: 0000000000000bf8 8 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL9kint
57: 0000000000000c00 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL10kui
58: 0000000000000c08 8 OBJECT LOCAL DEFAULT 14 _ZN6google8protobufL10kui
59: 0000000000000c10 4 OBJECT LOCAL DEFAULT 14 _ZN6google8protobuf8inter
60: 0000000000000c14 4 OBJECT LOCAL DEFAULT 14 _ZN3cay3logL9Level_MINE
61: 0000000000000c18 4 OBJECT LOCAL DEFAULT 14 _ZN3cay3logL9Level_MAXE
62: 0000000000000c1c 4 OBJECT LOCAL DEFAULT 14 _ZN3cay3logL15Level_ARRAY
63: 0000000000000c20 4 OBJECT LOCAL DEFAULT 14 _ZN3cay3logL13DEFAULT_LEV
64: 000000000020206a 1 OBJECT LOCAL DEFAULT 24 _ZN5boostL4noneE
65: 0000000000000c24 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL13days_per
66: 0000000000000c28 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL18days_per
67: 0000000000000c2c 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL16days_per
68: 0000000000000c30 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL18days_per
69: 0000000000000c34 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL18days_per
70: 0000000000000c38 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL12min_per_
71: 0000000000000c40 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL12sec_per_
72: 0000000000000c48 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL11ms_per_h
73: 0000000000000c50 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL11us_per_h
74: 0000000000000c58 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL11ns_per_h
75: 0000000000000c60 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL11sec_per_
76: 0000000000000c68 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10ms_per_m
77: 0000000000000c70 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10us_per_m
78: 0000000000000c78 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10ns_per_m
79: 0000000000000c80 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10ms_per_s
80: 0000000000000c84 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10us_per_s
81: 0000000000000c88 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10ns_per_s
82: 0000000000000c90 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10sec_per_
83: 0000000000000c98 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9us_per_ms
84: 0000000000000c9c 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9ns_per_ms
85: 0000000000000ca0 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10sec_per_
86: 0000000000000ca8 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9ms_per_us
87: 0000000000000cb0 4 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9ns_per_us
88: 0000000000000cb8 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL10sec_per_
89: 0000000000000cc0 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9ms_per_ns
90: 0000000000000cc8 8 OBJECT LOCAL DEFAULT 14 _ZN3cay6chronoL9us_per_ns
91: 0000000000000b1c 134 FUNC LOCAL DEFAULT 12 _Z41__static_initializati
92: 0000000000000ba2 21 FUNC LOCAL DEFAULT 12 _GLOBAL__sub_I_lib_elfhoo
93: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
94: 0000000000000dd8 0 OBJECT LOCAL DEFAULT 16 __FRAME_END__
95: 0000000000201dd8 0 OBJECT LOCAL DEFAULT 19 __JCR_END__
96: 0000000000000000 0 FILE LOCAL DEFAULT ABS
97: 0000000000000cd8 0 NOTYPE LOCAL DEFAULT 15 __GNU_EH_FRAME_HDR
98: 0000000000202000 0 OBJECT LOCAL DEFAULT 22 _GLOBAL_OFFSET_TABLE_
99: 0000000000202068 0 OBJECT LOCAL DEFAULT 23 __TMC_END__
100: 0000000000202060 0 OBJECT LOCAL DEFAULT 23 __dso_handle
101: 0000000000201de0 0 OBJECT LOCAL DEFAULT 20 _DYNAMIC
102: 0000000000000a70 172 FUNC GLOBAL DEFAULT 12 _ZN10ElfHookAPI4workEv
103: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
104: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
105: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts##GLIBC_2.2.5
106: 0000000000000bc4 0 FUNC GLOBAL DEFAULT 13 _fini
107: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev##
108: 0000000000000bb8 11 FUNC WEAK DEFAULT 12 _ZN5boost6none_tC1ENS0_8i
109: 0000000000000000 0 FUNC GLOBAL DEFAULT UND recv##GLIBC_2.2.5
110: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit##GLIBC_2.2.5
111: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev##
112: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
113: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
114: 0000000000000000 0 FUNC GLOBAL DEFAULT UND listen##GLIBC_2.2.5
115: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize##GLIBC_2.2
116: 0000000000000bb8 11 FUNC WEAK DEFAULT 12 _ZN5boost6none_tC2ENS0_8i
117: 0000000000000000 0 FUNC GLOBAL DEFAULT UND socket##GLIBC_2.2.5
118: 0000000000202068 0 NOTYPE GLOBAL DEFAULT 24 __bss_start
119: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail##GLIBC_2
120: 0000000000000000 0 FUNC GLOBAL DEFAULT UND send##GLIBC_2.2.5
121: 0000000000202070 0 NOTYPE GLOBAL DEFAULT 24 _end
122: 0000000000202068 0 NOTYPE GLOBAL DEFAULT 23 _edata
123: 0000000000000898 0 FUNC GLOBAL DEFAULT 9 _init
So what basically his code does is when you create shared library libtest.so that calls libc.so within it the following items are created within your library
a dynamic symbol table ( that includes data of all functions you are calling from libc.so )
a relocation table ( a list of entries within your code that called the functions within libc.so, every entry in a relocation table says that function X that belongs to libc.so was called in libtest.so in lines a,b,c...
His code parses your shared library, pulls the dynsymtable and the relocation table out of it and swaps symbols to your request by calling elf_hook() (see elf_hook.c lines 434 - 442).
You called three functions out of the libc.so API, which is a HUGE API, hence the dynsym in your table should contain symbols for socket() listen() and recv()
We can see dyn-symbols 13 11 and 6 are accordingly socket#GLIBC, listen#GLIBC and recv#GLIBC.
What the relocation table does is basically say where within the ACTUAL code of yours are those functions called, and when those symbols would have a resolved address which addresses would need to be replaced in order for your code to call the actual functions, as we also can see at .rela.plt you've posted as an output of the readelf command we see that on 3 different entries you've called theses symbols. These are what we need to replace.
So what his code does is find the index of the symbol you're looking to replace, go through ALL relocations, and see if they are relevant to the index-symbol. If so that means that in the place this relocation entry is relevant, it needs to replace it with the code you want.
Back with our previous example, lets say you want to replace socket() with y() in your libtest.so. His code finds the symbol index of socket(), finds where in code have you called socket() and replaces that with the address of y() instead.
Trying to hook symbols which don't exist
What can go wrong is the fact that when trying to hook symbols that weren't called is that simply there are no relocation entries for that symbol AND that symbol doesn't exist, you can see that e.g there is no entry in the dynsym table ( readelf output ) of bind().
What SHOULD happen is that he wouldn't find the according symbol and wont hook anything.
I honestly haven't gone through his entire code but my guess is that something went wrong there and he didn't handle the case of trying to hook a symbol that doesn't exist right...
Note:
Another thing that I've noticed that seems to be terrible wrong is the filling relocations of rel.dyn.
He has chosen to load the libs in his example with RTLD_LAZY, which basically means that every call to a DLL function would end up in jumping to some table of offsets, which point to your dynamic linker, and when the dynamic linker is called it replaces the offset which it was called from with the actual offset of the function... this is run-time relocation...
As far as I know rel.dyn is usually meant for load-time relocation, when the operating system loads an executable it copies it's code and looks at all the relocation entries and replaces them in code....
During run-time the offsets a rel.dyn table entries are pointing at would be within an executable section of the executable image, which means they SHOULD have only READ / EXECUTE permissions, not WRITE hence attempting to write into them SHOULD cause some segfault....
To sum things up, this probably happens because his utility didn't handle trying to hook an API function that does not exist within symbol table ( not called within your code ) right... hopefully I've helped you understand a little bit more of what happened...
Also, try reading this, it helped me to learn a lot about the ELF subject back in the day :)
http://flint.cs.yale.edu/cs422/doc/ELF_Format.pdf