Sometimes when reversing the code - I see that each linked file is separated by these functions:
_$E19
_$E18
sometimes - there is no such separation (depending on the degree of compiler optimization).
What is their meaning?
.text:0000021C
.text:0000021C ; =============== S U B R O U T I N E =======================================
.text:0000021C
.text:0000021C
.text:0000021C _$E19 proc near ; DATA XREF: .CRT$XCU:_$S20o
.text:0000021C mov cl, byte ptr ds:??_B?1???id@?$ctype@G@std@@$D@@9@51
.text:00000222 mov al, 1
.text:00000224 test al, cl
.text:00000226 jnz short loc_230
.text:00000228 or cl, al
.text:0000022A mov byte ptr ds:??_B?1???id@?$ctype@G@std@@$D@@9@51, cl
.text:00000230
.text:00000230 loc_230: ; CODE XREF: _$E19+Aj
.text:00000230 jmp _$E18
.text:00000230 _$E19 endp
.text:00000230
.text:00000230 ; ---------------------------------------------------------------------------
.text:00000235 db 7 dup(90h)
.text:00000235 _text ends
.text:00000235
.text:0000023C ; ===========================================================================
.text:0000023C
.text:0000023C ; Segment type: Pure code
.text:0000023C ; Segment permissions: Read/Execute
.text:0000023C _text segment para public 'CODE' use32
.text:0000023C assume cs:_text
.text:0000023C ;org 23Ch
.text:0000023C ; COMDAT (pick no duplicate)
.text:0000023C assume es:nothing, ss:nothing, ds:_CRT$XCU, fs:nothing, gs:nothing
.text:0000023C
.text:0000023C ; =============== S U B R O U T I N E =======================================
.text:0000023C
.text:0000023C
.text:0000023C _$E18 proc near ; CODE XREF: _$E19:loc_230j
.text:0000023C push offset ?id@?$ctype@G@std@@$E ; void (__cdecl *)()
.text:00000241 call _atexit
.text:00000246 pop ecx
.text:00000247 retn
.text:00000247 _$E18 endp
.text:00000247
.text:00000247 ; ---------------------------------------------------------------------------
.text:00000248 db 4 dup(90h)
.text:00000248 _text ends
.text:00000248
for example:
class aa
{
public:
aa();
~aa();
void fun();
};
class bb
{
public:
bb();
~bb();
void fun();
};
class cc
{
public:
cc();
~cc();
void fun();
};
// IMPLEMENTATION
aa::aa()
{
}
aa::~aa()
{
}
void aa::fun()
{
printf("aa called");
}
// ------------------------
bb::bb()
{
}
bb::~bb()
{
}
void bb::fun()
{
printf("bb called");
std::string s = "asd"; // <------------ reason
}
// --------------------------
cc::cc()
{
}
cc::~cc()
{
}
void cc::fun()
{
printf("cc called");
}
generates this list of functions:
aa::aa(void)
aa::~aa(void)
aa::fun(void)
bb::bb(void)
bb::~bb(void)
bb::fun(void)
std::basic_string<char,std::char_traits<char>,std::allocator<char>>::_Grow(uint,bool)
std::basic_string<char,std::char_traits<char>,std::allocator<char>>::_Copy(uint)
$E19
$E18
[thunk]:std::ctype<ushort>::id`template static data member destructor helper'
cc::cc(void)
cc::~cc(void)
cc::fun(void)
_main
_printf
But, the global variable initialized by the functions (_$E19
, _$E18
)
is never used.
i'm vote for the new tag: code-generation
_$E19
is the code that registers or unregisters (00000224 with subsequentjnz
or "fallthrough") the routine referenced at 0000023C with atexit. Now, I could be wrong and without further context I won't dare to answer this, but perhaps it helps you on your way to find out.