`nm` and `objdump` unknown dollar signed symbol - c

Th nm source.o gives unknown symbols:
F:\STM32CubeIDE\LMS\ANC_fxlms_v1\Debug\Core\Src>nm FX_LMS.o
00000000 b $d
00000298 t $d
00000000 b $d
000000b4 t $d
00000000 b $d
00000544 t $d
00000024 t $d
00000000 b $d
000002b0 t $d
00000000 d $d
000001f8 t $d
00000000 b $d
00000178 t $d
00000000 b $d
00000000 b $d
00000000 b $d
000000f0 t $d
00000000 b $d
00000058 t $d
00000000 b $d
00000000 b $d
00000000 b $d
00000000 b $d
00000000 b $d
00000050 t $d
00000000 b $d
000005ec t $d
00000000 b $d
00000664 t $d
00000000 b $d
00000000 b $d
0000003c t $d
00000000 t $t
.
.
.
00000000 t $t
00000000 t $t
U ADC_DMAError
U ADC_Enable
00000001 T ADC_Start_DMA_double
0000010c d aecho.0
.
.
.
I want to know the meaning of the $d and $t symbol. What is that? What is a reference that explain those?
This is the compiled C source from eclipse (STM32cubeIDE on Windows 10 64-bit).
The maybe important build commands copied from eclipse console:
21:04:01 **** Incremental Build of configuration Debug for project ANC_fxlms_v1 ****
make -j8 all
arm-none-eabi-gcc "../Core/Src/FX_LMS.c" -mcpu=cortex-m7 -std=gnu11 -g3 -DDEBUG -DARM_MATH_CM7 -DUSE_HAL_DRIVER -DSTM32H743xx -c -I../Core/Inc -I"F:/STM32CubeIDE/LMS/ANC_fxlms_v1/Core/Inc/drv" -I"F:/STM32CubeIDE/LMS/ANC_fxlms_v1/Drivers/CMSIS/DSP/Include" -I../Drivers/STM32H7xx_HAL_Driver/Inc -I../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy -I../Drivers/CMSIS/Device/ST/STM32H7xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -MMD -MP -MF"Core/Src/FX_LMS.d" -MT"Core/Src/FX_LMS.o" --specs=nano.specs -mfpu=fpv5-d16 -mfloat-abi=hard -mthumb -o "Core/Src/FX_LMS.o"
and here is the source:

You compiled the file for ARM architecture.
nm is for your local architecture. So most probably x86-64-pc-linux-gnu-nm or something like that.
arm-none-eabi-nm is for ARM architecture.
The endianess or some other quirks in the exact specification of ELF file may differ between architectures, which is most probably why you are seeing such artifacts.

Related

How to sort the symbol table (generated by "objdump -t") sequentially by address?

I would like to see at one glance which variables are placed next to each other in memory.
If I generate a symbol table by using objdump -t I get the symbol table, however sorted seemingly randomly.
SYMBOL TABLE:
00100584 l F .text 00000000 deregister_tm_clones
001005a8 l F .text 00000000 register_tm_clones
001005d4 l F .text 00000000 __do_global_dtors_aux
0019c020 l .bss 00000001 completed.10177
0019c00c l O .fini_array 00000000 __do_global_dtors_aux_fini_array_entry
00100604 l F .text 00000000 frame_dummy
0019c024 l .bss 00000018 object.10182
0019c008 l O .init_array 00000000 __frame_dummy_init_array_entry
00000000 l df *ABS* 00000000 tcp_server_test.c
0019c03c l .bss 00000004 xServerWorkTaskHandle
001006a4 l F .text 00000098 prvServerWorkTask
0019c040 l .bss 00000008 xMyTelnet
...
Is there a way to get it sorted by address (first column) in upcounting manner?
It would be great if there was a switch that could be added to objdump -t to get the desired output. I looked through the documentation and did not find anything like that, but maybe I overlooked something?
Another approach could be to write a python script that resorts it, but I would like to avoid that if possible.
Thanks!
You can use the universal tool "sort" to sort the output of "objdump".
Please read its documentation for options. Without any option, it simply sorts on the first column.
For the no-yet-enlightened command line user...
You need to "pipe" the output of "objdump" as input into "sort" like this:
objdump -t my_module.o | sort

ESP8266 Chip crash after some time

I run a server in ESP8266 which accept argument and value when you click the submit button in the webpage. after some iteration of clicking the submit button, the esp8266 crashes with the Exception of:
--------------- CUT HERE FOR EXCEPTION DECODER ---------------
Exception (29):
epc1=0x40205224 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
>>>stack>>>
ctx: cont
sp: 3ffffca0 end: 3fffffc0 offset: 0190
3ffffe30: 3fff1598 3fff1598 3ffffe80 4020521f
3ffffe40: 3fff6354 3ffffe98 3ffffe80 40217ef0
3ffffe50: 00000003 3ffffec0 3ffffe80 40217f20
3ffffe60: 3ffffe98 3ffffea4 3fff1588 3fff0da4
3ffffe70: 00000000 3ffffec0 00000005 402053a9
3ffffe80: 3fff631c 0029002f 00003a30 3fff6300
3ffffe90: 0029002f 800001da 3fff6354 0029002f
3ffffea0: 00000001 3fffbf5c 0005002f 00217d42
3ffffeb0: 00000001 3fff0dac 3ffffefc 4020cb24
3ffffec0: 3fff68b4 01da01df 00000000 fffffffe
3ffffed0: 00000000 3fffc6fc 00000000 3fff1c88
3ffffee0: 00000000 3fffdad0 40223278 00000000
3ffffef0: 3ffffefc 3fffff64 3fff0a00 40223428
3fffff00: 00000000 000003e8 3fffff60 03e87701
3fffff10: 402583d1 00000004 3fff0d58 4020171a
3fffff20: 40258677 00000004 3fff0d58 3fff0d5c
3fffff30: 00000000 4bc6a7f0 0189374b 00000000
3fffff40: 00000000 00000000 4bc6a7f0 00000000
3fffff50: 000e001a 00050008 4010051c 0001fc51
3fffff60: 00000000 6c80e048 4024c800 3ffe8514
3fffff70: 024bbda9 80000000 00000000 4010059d
3fffff80: 00000000 00000000 00000001 3fff1cc8
3fffff90: 3fffdad0 00000000 0001fc51 40211f35
3fffffa0: 3fffdad0 00000000 3fff1c88 40218fd4
3fffffb0: feefeffe feefeffe 3ffe899c 40100f45
<<<stack<<<
last failed alloc call: 4020521F(100)
--------------- CUT HERE FOR EXCEPTION DECODER ---------------
ets Jan 8 2013,rst cause:2, boot mode:(3,6)
For debugging: Free Heap is printed(runs every 2 seconds using millis) in the serial monitor by
Serial.println(ESP.getFreeHeap());
The submit button is sending the following argument and value(Partial only) :
http://192.168.4.1?user=1234&password=1234&data1=qwertyuiopasdfghjklzxcvbnm&data1=qwertyuiopasdfghjklzxcvbnm&data2=qwertyuiopasdfghjklzxcvbnm&data3=qwertyuiopasdfghjklzxcvbnm&data4=qwertyuiopasdfghjklzxcvbnm
as you can see the FreeHeap is going down until it reaches the minimum where ESP8266 can't handle.
Is there a way to refresh or reuse the heap without rebooting the Chip?
Is safeString can help to this problem ?

Unix Executable File 'Exec', hex dump shows C code, not Assembly

In Os X, I compiled a C program with the command: gcc -o binaryoutName inputfile which I created and then ran a hex dump on the resultant binary "Exec" file. As I understand it, an Exec file is a 'UNIX Executable', which is the UNIX equivalent of an executable file.
When I ran the hex dump using the command xxd -b binary, it returned the ASCII content of the binary, however this ASCII represented the literal C code which i first programmed the .c file in.
Hex dump Extract:
0007c4a: 01101100 01110101 01110011 01101000 00000000 01011111 lush._
0007c50: 01100110 01101111 01110000 01100101 01101110 00000000 fopen.
0007c56: 01011111 01100110 01110000 01110010 01101001 01101110 _fprin
0007c5c: 01110100 01100110 00000000 01011111 01100111 01100101 tf._ge
0007c62: 01110100 01100011 01101000 01100001 01110010 00000000 tchar.
0007c68: 01011111 01100111 01100101 01110100 01100011 01110111 _getcw
0007c6e: 01100100 00000000 01011111 01100111 01100101 01110100 d._get
0007c74: 01100101 01101110 01110110 00000000 01011111 01101100 env._l
0007c7a: 01101111 01100011 01100001 01101100 01110100 01101001 ocalti
0007c80: 01101101 01100101 00000000 01011111 01101101 01100101 me._me
0007c86: 01101101 01100011 01110000 01111001 00000000 01011111 mcpy._
0007c8c: 01110000 01110010 01101001 01101110 01110100 01100110 printf
0007c92: 00000000 01011111 01110000 01110101 01110100 01100011 ._putc
0007c98: 01101000 01100001 01110010 00000000 01011111 01110011 har._s
0007c9e: 01100011 01100001 01101110 01100110 00000000 01011111 canf._
0007ca4: 01110011 01101100 01100101 01100101 01110000 00000000 sleep.
Note that the ASCII translation on the far-right column is extremely similar to the code inside the .c file I initially compiled.
This is counter-intuitive as I expected the hex dump to contain the ASCII binary of the Assembly code which the compiler would logically compile it too.
This is a question at the very limits of my understanding of the compilation process and I expect to have a few incorrect details, for which I apologies.
My Question: Why did the hex dump return ASCII for C code instead of Assembly?
Thanks in Advance.
I believe what you saw is the .strtab section (or similar sections) of your executable or object file, which does include string.
For example, for the following C program:
#include <stdio.h>
int main(void)
{
printf("Hello world!\n");
}
Compiled with the following command:
gcc -Wall -g -std=c11 c00.c
If we hexdump it, we will find something like:
$ xxd a.out
...
00022e0: 0000 0000 0000 0000 0063 7274 7374 7566 .........crtstuf
00022f0: 662e 6300 5f5f 4a43 525f 4c49 5354 5f5f f.c.__JCR_LIST__
0002300: 0064 6572 6567 6973 7465 725f 746d 5f63 .deregister_tm_c
0002310: 6c6f 6e65 7300 7265 6769 7374 6572 5f74 lones.register_t
0002320: 6d5f 636c 6f6e 6573 005f 5f64 6f5f 676c m_clones.__do_gl
...
And we can find out the section related information through
$ readelf -WS a.out
...
[34] .strtab STRTAB 0000000000000000 0022e8 000235 00 0 0 1
Notices the offset of .strtab is 0x0022e8, which matches what we saw from the output of xxd.
What you see is not C code but the table of symbols of your executable or object file (symbols that have external linkage property). An object file or executable is formatted (Linux uses ELF standard for example) into different sections: symbol table, global variables, code, etc. For the symbol table, the compiler generates it for different purpose as to generate linkable files or ease debug.
In an executable, these symbols are not mandatory and you can easily remove them with command strip, if you strip an object file you will be unable to link it.
You can show in a more readable form the content of the symbol table with commands like nm.
Read online manual for strip and nm commands, how compilers link object files...

Virtual memory addresses of objdump vs /proc/pid/maps?

I'm trying to understand where exactly does the executable assembly of a program end up, when a program is loaded/running. I found two resources talking about this, but they are somewhat difficult to read:
Understanding ELF using readelf and objdump Linux article (code formatting is messed up)
Michael Guyver, Some Assembly Required*: Relocations, Relocations (lots of assembly which I'm not exactly proficient in)
So, here's a brief example; I'm interested where does the executable section of the tail program end up. Basically, objdump tells me this:
$ objdump -dj .text /usr/bin/tail | head -10
/usr/bin/tail: file format elf32-i386
Disassembly of section .text:
08049100 <.text>:
8049100: 31 ed xor %ebp,%ebp
8049102: 5e pop %esi
8049103: 89 e1 mov %esp,%ecx
...
I'm assuming I'd see calls to tail's 'main()' be made here, had symbols not been stripped. Anyways, the start of the executable section is, according to this, 0x08049100; I'm interested in where it ends up eventually.
Then, I run tail in the background, getting its pid:
$ /usr/bin/tail -f & echo $!
28803
... and I inspect its /proc/pid/maps:
$ cat /proc/28803/maps
00547000-006a8000 r-xp 00000000 08:05 3506 /lib/i386-linux-gnu/libc-2.13.so
...
008c6000-008c7000 r-xp 00000000 00:00 0 [vdso]
08048000-08054000 r-xp 00000000 08:05 131469 /usr/bin/tail
08054000-08055000 r--p 0000b000 08:05 131469 /usr/bin/tail
08055000-08056000 rw-p 0000c000 08:05 131469 /usr/bin/tail
08af1000-08b12000 rw-p 00000000 00:00 0 [heap]
b76de000-b78de000 r--p 00000000 08:05 139793 /usr/lib/locale/locale-archive
...
bf845000-bf866000 rw-p 00000000 00:00 0 [stack]
Now I have tail three times - but the executable segment r-xp (which is the .text?) is apparently at 0x08048000 (an address that apparently was standardized back with SYSV for x86; also see Anatomy of a Program in Memory : Gustavo Duarte for an image)
Using the gnuplot script below, I arrived at this image:
First (topmost) plot shows "File offset" of sections from objdump (starts from 0x0); middle plot shows "VMA" (virtual memory address) of sections from objdump and bottom plot shows layout from /proc/pid/maps - both of these starting from 0x08048000; all three plots show the same range.
Comparing topmost and middle plot, it seems that the sections are more-less translated "as is" from the executable file to the VMA addresses (apart from the end); such that the whole executable file (not just .text section) starts from 0x08048000.
But comparing middle and bottom plot, it seems that when a program is running in memory, then only .text is "pushed back" to 0x08048000 - and not only that, it now appears larger!
The only explanation I have so far, is what I read somewhere (but lost the link): that an image in memory would have to have allocated a whole number of pages (of size e.g. 4096 bytes), and start from a page boundary. The whole number of pages explains the larger size - but, given that all these are virtual addresses, why the need to "snap" them to a page boundary (could one not, just as well, map the virtual address as is to a physical page boundary?)
So - could someone provide an explanation so as to why /proc/pid/maps sees the .text section in a different virtual address region from objdump?
mem.gp gnuplot script:
#!/usr/bin/env gnuplot
set term wxt size 800,500
exec = "/usr/bin/tail" ;
# cannot do - apparently gnuplot waits for children to exit, so locks here:
#runcmd = "bash -c '" . exec . " -f & echo $!'"
#print runcmd
#pid = system(runcmd) ;
#print runcmd, "pid", pid
# run tail -f & echo $! in another shell; then enter pid here:
pid = 28803
# $1 Idx $2 Name $3 Size $4 VMA $5 LMA $6 File off
cmdvma = "<objdump -h ".exec." | awk '$1 ~ \"^[0-9]+$\" && $2 !~ \".gnu_debuglink\" {print $1, $2, \"0X\"$3, \"0X\"$4;}'" ;
cmdfo = "<objdump -h ".exec." | awk '$1 ~ \"^[0-9]+$\" && $2 !~ \".gnu_debuglink\" {print $1, $2, \"0X\"$3, \"0X\"$6;}'" ;
cmdmaps = "<cat /proc/".pid."/maps | awk '{split($1,a,\"-\");b1=strtonum(\"0x\"a[1]);b2=strtonum(\"0x\"a[2]);printf(\"%d \\\"%s\\\" 0x%08X 0x%08X\\n\", NR,$6,b2-b1,b1);}'"
print cmdvma
print cmdfo
print cmdmaps
set format x "0x%08X" # "%016X";
set xtics rotate by -45 font ",7";
unset ytics
unset colorbox
set cbrange [0:25]
set yrange [0.5:1.5]
set macros
set multiplot layout 3,1 columnsfirst
# 0x08056000-0x08048000 = 0xe000
set xrange [0:0xe000]
set tmargin at screen 1
set bmargin at screen 0.667+0.1
plot \
cmdfo using 4:(1+$0*0.01):4:($4+$3):0 with xerrorbars lc palette t "File off", \
cmdfo using 4:(1):2 with labels font ",6" left rotate by -45 t ""
set xrange [0x08048000:0x08056000]
set tmargin at screen 0.667
set bmargin at screen 0.333+0.1
plot \
cmdvma using 4:(1+$0*0.01):4:($4+$3):0 with xerrorbars lc palette t "VMA", \
cmdvma using 4:(1):2 with labels font ",6" left rotate by -45 t ""
set tmargin at screen 0.333
set bmargin at screen 0+0.1
plot \
cmdmaps using 4:(1+$0*0.01):4:($4+$3):0 with xerrorbars lc palette t "/proc/pid/maps" , \
cmdmaps using 4:(1):2 with labels font ",6" left rotate by -45 t ""
unset multiplot
#system("killall -9 " . pid) ;
The short answer is that loadable segments get mapped into memory based on the ELF program headers with type PT_LOAD.
PT_LOAD - The array element specifies a loadable segment, described by
p_filesz and p_memsz. The bytes from the file are mapped to the
beginning of the memory segment. If the segment's memory size
(p_memsz) is larger than the file size (p_filesz), the ``extra'' bytes
are defined to hold the value 0 and to follow the segment's
initialized area. The file size may not be larger than the memory
size. Loadable segment entries in the program header table appear in
ascending order, sorted on the p_vaddr member.
For example, on my CentOS 6.4:
objdump -x `which tail`
Program Header:
LOAD off 0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
filesz 0x0000e4d4 memsz 0x0000e4d4 flags r-x
LOAD off 0x0000e4d4 vaddr 0x080574d4 paddr 0x080574d4 align 2**12
filesz 0x000003b8 memsz 0x0000054c flags rw-
And from /proc/pid/maps:
cat /proc/2671/maps | grep `which tail`
08048000-08057000 r-xp 00000000 fd:00 133669 /usr/bin/tail
08057000-08058000 rw-p 0000e000 fd:00 133669 /usr/bin/tail
You will notice there is a difference between what maps and objdump says for the load address for subsequent sections, but that has to do with the loader accounting how much memory the section takes up as well as the alignment field. The first loadable segment is mapped in at 0x08048000 with a size of 0x0000e4d4, so you'd expect it to go from 0x08048000 to 0x080564d4, but the alignment says to align on 2^12 byte pages. If you do the math you end up at 0x8057000, matching /proc/pid/maps. So the second segment is mapped in at 0x8057000 and has a size of 0x0000054c (ending at 0x805754c), which is aligned to 0x8058000, matching /proc/pid/maps.
Thanks to the comment from #KerrekSB, I reread Understanding ELF using readelf and objdump - Linux article, and I think I sort of got it now (although it would be nice for someone else to confirm if its right).
Basically, the mistake is that the region 08048000-08054000 r-xp 00000000 08:05 131469 /usr/bin/tail from /proc/pid/maps does not start with .text section; and the missing link for knowing this is Program Header Table (PHT), as reported by readelf. Here is what it says for my tail:
$ readelf -l /usr/bin/tail
Elf file type is EXEC (Executable file)
Entry point 0x8049100
There are 9 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
[00] PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4
[01] INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
[02] LOAD 0x000000 0x08048000 0x08048000 0x0b9e8 0x0b9e8 R E 0x1000
[03] LOAD 0x00bf10 0x08054f10 0x08054f10 0x00220 0x003f0 RW 0x1000
[04] DYNAMIC 0x00bf24 0x08054f24 0x08054f24 0x000c8 0x000c8 RW 0x4
[05] NOTE 0x000168 0x08048168 0x08048168 0x00044 0x00044 R 0x4
[06] GNU_EH_FRAME 0x00b918 0x08053918 0x08053918 0x00024 0x00024 R 0x4
[07] GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
[08] GNU_RELRO 0x00bf10 0x08054f10 0x08054f10 0x000f0 0x000f0 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .ctors .dtors .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .ctors .dtors .jcr .dynamic .got
I've added the [0x] line numbering in the "Program Headers:" section manually; otherwise it's hard to link it to Section to Segment mapping: below. Here also note: "Segment has many types, ... LOAD: The segment's content is loaded from the executable file. "Offset" denotes the offset of the file where the kernel should start reading the file's content. "FileSiz" tells us how many bytes must be read from the file. (Understanding ELF...)"
So, objdump tells us:
08049100 <.text>:
... that .text section starts at 0x08049100.
Then, readelf tells us:
[02] LOAD 0x000000 0x08048000 0x08048000 0x0b9e8 0x0b9e8 R E 0x1000
... that header/segment [02] is loaded from the executable file at offset zero into 0x08048000; and that this is marked R E - read and execute region of memory.
Further, readelf tells us:
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
... meaning that the header/segment [02] contains many sections - among them, also the .text; this now matches with the objdump view that .text starts higher than 0x08048000.
Finally, /proc/pid/maps of the running program tells us:
08048000-08054000 r-xp 00000000 08:05 131469 /usr/bin/tail
... that the executable (r-xp) "section" of the executable file is loaded at 0x08048000 - and now it is easy to see that this "section", as I called it, is called wrong - it is not a section (as per objdump nomenclature); but it is actually a "header/segment", as readelf sees it (in particular, the header/segment [02] we saw earlier).
Well, hopefully I got this right ( and hopefully someone can confirm if I did so or not :) )

Help Deadlock analysis

The Deadlock occurs in my application when initialization of local static variable happens in the function called from DLLMain Entry point with param DLL_THREAD_DETACH.
Below is Windbg analysis
This is usually caused by another thread holding the loader lock.
Following are the Locks Held.
CritSec ntdll!LdrpLoaderLock+0 at 7c97e178
LockCount 3
RecursionCount 1
OwningThread 17e8
EntryCount d
ContentionCount d
*** Locked
CritSec MSVCR80!__app_type+94 at 781c3bc8
LockCount 1
RecursionCount 1
OwningThread 1100
EntryCount 1
ContentionCount 1
*** Locked
#
Call stack Thread 17e8
781c3bc8 78132bd9 0777fde4 ntdll!RtlEnterCriticalSection+0x46
00000008 b87d2630 00000000 MSVCR80!_lock+0x2e
0864ae10 08631d7f 0864ae10 EPComUtilities32!_onexit+0x36
0864ae10 b87d2588 00000001 EPComUtilities32!atexit+0x9
0777fea8 0864719f 08630000 EPComUtilities32!XCriticalSectionEx::ThreadTerminated+0x5f
08630000 00000003 00000000 EPComUtilities32!DllMain+0x20
08630000 7c90118a 08630000 EPComUtilities32!__DllMainCRTStartup+0x7a
08630000 00000003 00000000 EPComUtilities32!_DllMainCRTStartup+0x1d
#
Call Stack thread 1100
000000b0 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc
000000b0 ffffffff 00000000 kernel32!WaitForSingleObjectEx+0xa8
000000b0 ffffffff 06ce64e0 kernel32!WaitForSingleObject+0x12
000480ba 000f4240 00000000 CATSysMultiThreading!CATThreads::Join+0xf5
0012fcc8 00000004 00000000 JS0GROUP!CATLM::StopHB+0xf4
d138509f 00416694 00000001 JS0GROUP!CATLM::Unmake+0x6b
00000000 00000000 00000000 MSVCR80!_cinit+0xd6
00000000 0012fd6c 081e68d9 MSVCR80!exit+0xd
00000000 06d404f0 0998fb90 JS0GROUP!CATExit+0x1d
00000000 004ef366 0000000d DNBPLMProvider!DNBEPLMTransactionMgt::OnApplicationExit+0x229
00000000 0012fd9c 004eabfc JS0GROUP!CATCallExits+0x2bc
00000000 0012ff7c 0040cefd JS0GROUP!CATErrorNormalEnd+0x31
00000000 06ce71d0 06ce71d0 JS0GROUP!CATExit+0xc
00000007 06cdb120 059b61d8 DLMMfgContextSolver!main+0x146d
ffffffff ffffffff bffde000 DLMMfgContextSolver!__tmainCRTStartup+0x10f
#
Please give you comments to understand what might have caused the deadlock.
Note: the moment i make the static variable as non static the problem disappears this in context of example posted in forum Deadlock occurs in Function Scoped Static variables (Thread Unsafe in VC++)
In short, what caused the deadlock is that you did something non-trivial in DllMain.

Resources