Name mangling in MASM (ML64) is inconsistent - masm

With the following file and using the Microsoft assembler ML64 (v14.00.2410.0, that ships with VS 2015), the assembler is mangling the name of the first routine (asm_cli) by adding an underscore, but it doesn't mangle the name of the second routine (asm_diable_vm). Why? The listing file doesn't show the name mangling, but LINK/DUMP on the .OBJ file shows the addition of the underscore.
Partial output from LINK/DUMP
RELOCATIONS #3
Symbol Symbol
Offset Type Applied To Index Name
-------- ---------------- ----------------- -------- ------
00000070 SECREL 00000000 C $$000000
00000074 SECTION 0000 C $$000000
00000225 SECREL 00000000 A _asm_cli
00000229 SECTION 0000 A _asm_cli
00000259 SECREL 00000000 B asm_disable_vm
0000025D SECTION 0000 B asm_disable_vm
COFF SYMBOL TABLE
000 01035E92 ABS notype Static | #comp.id
001 00000010 ABS notype Static | #feat.00
002 00000000 SECT1 notype Static | .text$mn
Section length 25, #relocs 0, #linenums 0, checksum 0
004 00000000 SECT2 notype Static | .data
Section length 0, #relocs 0, #linenums 0, checksum 0
006 00000000 SECT3 notype Static | .debug$S
Section length 274, #relocs 6, #linenums 0, checksum 0
008 00000000 SECT4 notype Static | .debug$T
Section length 34, #relocs 0, #linenums 0, checksum 0
00A 00000000 SECT1 notype () External | _asm_cli
00B 00000010 SECT1 notype () External | asm_disable_vm
00C 00000000 SECT1 notype Static | $$000000
Assembly.asm
cr0_pg EQU 80000000h ; Paging bit. If set, enables paging (and uses CR3 as pointer to page tables)
cr4_pae EQU 20H ; Physical Address Extension. If set, uses extended page table size
;
; Declare an C-callable entry point
;
routine_start MACRO Name, Section
Section SEGMENT PARA 'CODE'
DB 6 DUP (0ccH) ; Padding required by the calling standard
ALIGN 16
PUBLIC Name
Name PROC FRAME
.ENDPROLOG
ENDM
;
; Declare the end of a routine
;
routine_end MACRO Name, Section
Name ENDP
Section ENDS
ENDM
routine_start asm_cli, _TEXT
CLI ; Disable interrupts
RET
routine_end asm_cli, _TEXT
routine_start asm_disable_vm, _TEXT
;
; Disable paging
;
MOV RAX, CR0 ; Get the contents of control register 0
AND EAX, 7fffffffH ; Clear the paging bit
MOV CR0, RAX ; Save back to the register
;
; Empty the Translation Look-aside Buffer (TLB) by clearing the address of the
; first-level page table
;
XOR RAX, RAX ; Clear EAX
MOV CR3, RAX ; Clear Control Register 3
;
; Disable Physical Address Extension (PAE)
;
MOV RAX, CR4 ; Get the contents of control register 4
AND AL, NOT cr4_pae ; Clear the PAE bit
MOV CR4, RAX ; Save back to the register
RET
routine_end asm_disable_vm, _TEXT
END

Related

What are these sections in a Linker's map file?

My COSMIC-C linker generates a map file for my STM8S microcontroller project, which despite having a few familiar sections, is a little inexpressive.
here is the map file output and a few modules :
--------
Segments
--------
start 00008080 end 00008084 length 4 segment .const
start 00008087 end 00008298 length 529 segment .text
start 00004000 end 00004000 length 0 segment .eeprom
start 00000000 end 00000000 length 0 segment .bsct
start 00000000 end 0000000a length 10 segment .ubsct
start 0000000a end 0000000a length 0 segment .bit
start 0000000a end 0000000a length 0 segment .share
start 00000100 end 00000100 length 0 segment .data
start 00000100 end 00000100 length 0 segment .bss
start 00000000 end 000003be length 958 segment .info.
start 00008000 end 00008080 length 128 segment .const
start 00008084 end 00008087 length 3 segment .init
-------
Modules
-------
D:\Program Files (x86)\COSMIC\FSE_Compilers\CXSTM8\lib\crtsi0.sm8:
start 00008087 end 000080d7 length 80 section .text
start 00000100 end 00000100 length 0 section .bss
start 00000000 end 00000000 length 0 section .ubsct
start 00000000 end 00000034 length 52 section .info.
Release\clockcontrol.o:
start 000080d7 end 000080f7 length 32 section .text
start 00000034 end 000000c1 length 141 section .info.
Release\main.o:
start 000080f7 end 00008145 length 78 section .text
start 000000c1 end 00000146 length 133 section .info.
start 00008080 end 00008084 length 4 section .const
I know about the .text and .data. and I can assume the bsct and ubsct are data and bss (despite having a .data and .bss already); also about .eeprom and .const which may represent their obvious memory sections. but :
what are .info, .bit, .share, .init ?
is my assumption about .bsct and .ubsct correct ? if no, what are these sections and if yes, why we have both .bsct/.ubsct and .data/.bss ?
why do we have two .const? (they are consecutive)
despite being defined, none of the items mentioned in question 1 appear in any modules which are my codes. are they just standards ?
do these sections follow a naming convention or they're just something out of COSMIC ? I mean if they are standard or not.
with many thanx.
Update:
the COSMIC linker documentation has many descriptions on how to make a linker script, but doesn't have a predefined table. it seems the script is edited by STVD (the IDE). despite that, there is an example (not very related to my question) which may help:

Compatability of cross-built COFF files and MSVS

I have cross-built a win32 static library using i686-w64-mingw32-gccon a linux box.
I have inspected the resulting .lib file with nm on the linux side and see:
bsd_offset.o:
U __assert
00000000 T _bsd_offset
00000000 b .bss
00000000 d .data
00000000 i .drectve
U _flp3
00000004 C _randNo
00000000 r .rdata
00000000 r .rdata$zzz
00000000 t .text
bsdi.o:
00000000 T _bsdi
00000000 b .bss
U _clp3
00000000 d .data
00000000 i .drectve
00000004 C _randNo
00000000 r .rdata$zzz
00000000 t .text
...
I have also inspected the .lib file with dumpbin /symbols on the windows side and see:
Microsoft (R) COFF/PE Dumper Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file libLib_rel.lib
File Type: LIBRARY
COFF SYMBOL TABLE
000 00000000 DEBUG notype Filename | .file
bsd_offset.c
002 00000000 SECT1 notype () External | _bsd_offset
tag index 00000000 size 00000000 lines 00000000 next function 00000000
004 00000000 SECT1 notype Static | .text
Section length BF, #relocs 4, #linenums 0, checksum 0
006 00000000 SECT2 notype Static | .data
Section length 0, #relocs 0, #linenums 0, checksum 0
008 00000000 SECT3 notype Static | .bss
Section length 0, #relocs 0, #linenums 0, checksum 0
00A 00000000 SECT4 notype Static | .rdata
Section length 1A, #relocs 0, #linenums 0, checksum 0
00C 00000000 SECT6 notype Static | .drectve
Section length 2C, #relocs 0, #linenums 0, checksum 0
00E 00000000 SECT7 notype Static | .rdata$zzz
Section length 1A, #relocs 0, #linenums 0, checksum 0
010 00000004 UNDEF notype External | _randNo
011 00000000 UNDEF notype () External | _flp3
012 00000000 UNDEF notype () External | __assert
String Table Size = 0x35 bytes
COFF SYMBOL TABLE
000 00000000 DEBUG notype Filename | .file
bsdi.c
002 00000000 SECT1 notype () External | _bsdi
tag index 00000000 size 00000000 lines 00000000 next function 00000000
004 00000000 SECT1 notype Static | .text
Section length 70, #relocs 1, #linenums 0, checksum 0
006 00000000 SECT2 notype Static | .data
Section length 0, #relocs 0, #linenums 0, checksum 0
008 00000000 SECT3 notype Static | .bss
Section length 0, #relocs 0, #linenums 0, checksum 0
00A 00000000 SECT5 notype Static | .drectve
Section length 26, #relocs 0, #linenums 0, checksum 0
00C 00000000 SECT6 notype Static | .rdata$zzz
Section length 1A, #relocs 0, #linenums 0, checksum 0
00E 00000004 UNDEF notype External | _randNo
00F 00000000 UNDEF notype () External | _clp3
String Table Size = 0x29 bytes
...
A colleague is attempting to build an exe using the lib using MSVS2008 and is seeing errors like:
1>------ Build started: Project: StaticLinkExample, Configuration: Release Win32 ------
1>Linking...
1>testLib_rel.lib(initialise.o) : warning LNK4229: invalid directive '/aligncomm:_randNo,2' encountered; ignored
1>testLib_rel.lib(lib.o) : warning LNK4229: invalid directive '/aligncomm:_randNo,2' encountered; ignored
...
1> Creating library D:\Software\ThirdParty\Lib_v230\Trial\StaticLinkExample\Release\StaticLinkExample.lib and object D:\Software\ThirdPart\Lib_v230\Trial\StaticLinkExample\Release\StaticLinkExample.exp
1>testLib_rel.lib(shared.o) : error LNK2001: unresolved external symbol ___ms_vsnprintf
1>testLib_rel.lib(iniparser.o) : error LNK2001: unresolved external symbol ___ms_vsnprintf
1>testLib_rel.lib(utility.o) : error LNK2001: unresolved external symbol ___ms_vsnprintf
1>testLib_rel.lib(load_glf.o) : error LNK2001: unresolved external symbol ___chkstk_ms
1>testLib_rel.lib(utility.o) : error LNK2001: unresolved external symbol ___chkstk_ms
1>testLib_rel.lib(lib.o) : error LNK2001: unresolved external symbol _fmax
1>testLib_rel.lib(lib.o) : error LNK2001: unresolved external symbol _fmin
1>StaticLinkExample.exp : error LNK2001: unresolved external symbol bsd_offset
1>StaticLinkExample.exp : error LNK2001: unresolved external symbol bsdi
Do the nm and dumpbin outputs look sensible. If the symbols are there in the static library why would the link errors be occuring. Could it be that somehow the cross-built lib is not binary compatible with MSVS 2008?

LLVM (arm-none-eabi target) is producing an ARM.exidx section for C based code(?)

Compiling a simple HelloWorld.c using Clang/LLVM (arm-none-eabi target) produces a relocation section '.rel.ARM.exidx' but using arm-gcc does not. These LLVM produced unwind table entries are correctly tagged as canunwind. But why are they even produced at all as they are not needed and just cause bloat as you get an entry for every C function in your AXF?
readelf edxidx from HelloWorld.o
Relocation section '.rel.ARM.exidx' at offset 0x580 contains 2 entries:
Offset Info Type Sym.Value Sym. Name
00000000 00000b2a R_ARM_PREL31 00000000 .text
00000008 00000b2a R_ARM_PREL31 00000000 .text
Unwind table index '.ARM.exidx' at offset 0xcc contains 2 entries:
0x0 <print_uart0>: 0x1 [cantunwind]
0x54 <c_entry>: 0x1 [cantunwind]
In testing Clang defaults: If I pass "-funwind-tables" to Clang to force unwinding for even C functions, I get what I would expect had I been writing .cpp functions and "-fno-unwind-tables" results in the same as above.
Relocation section '.rel.ARM.exidx' at offset 0x5a4 contains 4 entries:
Offset Info Type Sym.Value Sym. Name
00000000 00000b2a R_ARM_PREL31 00000000 .text
00000000 00001600 R_ARM_NONE 00000000 __aeabi_unwind_cpp_pr0
00000008 00000b2a R_ARM_PREL31 00000000 .text
00000008 00001600 R_ARM_NONE 00000000 __aeabi_unwind_cpp_pr0
Unwind table index '.ARM.exidx' at offset 0xcc contains 2 entries:
0x0 <print_uart0>: 0x8001b0b0
Compact model index: 0
0x01 vsp = vsp + 8
0xb0 finish
0xb0 finish
0x54 <c_entry>: 0x809b8480
Compact model index: 0
0x9b vsp = r11
0x84 0x80 pop {r11, r14}
1) Is there anyway to turn off the .ARM.exidx section when only using C functions as they will always be flagged as "cantunwind".
2) Anyway to strip this section during linking? (gc-section will not workof course since these table entries reference in-use functions)
3) Why does arm-gcc not create this section (well, it does if you are using new lib, nano, etc... but I use and link no std libs)
I'll answer (2), since that's what I did. Add to your linker script:
/DISCARD/ :
{
*(.ARM.exidx)
}

Link error between C and assembly

I'm compiling a c file foo.c:
#include <stdlib.h>
extern void *memcpy_optimized(void* __restrict, void* __restrict, size_t);
void foo() {
[blah blah blah]
memcpy_optimized((void *)a, (void *)b, 123);
}
then I have the assembly file memcpy_optimized.S:
.text
.fpu neon
.global memcpy_optimized
.type memcpy_optimized, %function
.align 4
memcpy_optimized:
.fnstart
mov ip, r0
cmp r2, #16
blt 4f # Have less than 16 bytes to copy
# First ensure 16 byte alignment for the destination buffer
tst r0, #0xF
beq 2f
tst r0, #1
ldrneb r3, [r1], #1
[blah blah blah]
.fnend
Both files compile fine with: gcc $< -o $# -c
but when I link the application with both resulting objects, I get the following error:
foo.c:(.text+0x380): undefined reference to `memcpy_optimized(void*, void *, unsigned int)'
Any idea what I'm doing wrong?
readelf -a obj/memcpy_optimized.o
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: ARM
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 436 (bytes into file)
Flags: 0x5000000, Version5 EABI
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 11
Section header string table index: 8
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000040 0000f0 00 AX 0 0 16
[ 2] .data PROGBITS 00000000 000130 000000 00 WA 0 0 1
[ 3] .bss NOBITS 00000000 000130 000000 00 WA 0 0 1
[ 4] .ARM.extab PROGBITS 00000000 000130 000000 00 A 0 0 1
[ 5] .ARM.exidx ARM_EXIDX 00000000 000130 000008 00 AL 1 0 4
[ 6] .rel.ARM.exidx REL 00000000 00044c 000010 08 9 5 4
[ 7] .ARM.attributes ARM_ATTRIBUTES 00000000 000138 000023 00 0 0 1
[ 8] .shstrtab STRTAB 00000000 00015b 000056 00 0 0 1
[ 9] .symtab SYMTAB 00000000 00036c 0000b0 10 10 9 4
[10] .strtab STRTAB 00000000 00041c 00002f 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no section groups in this file.
There are no program headers in this file.
Relocation section '.rel.ARM.exidx' at offset 0x44c contains 2 entries:
Offset Info Type Sym.Value Sym. Name
00000000 0000012a R_ARM_PREL31 00000000 .text
00000000 00000a00 R_ARM_NONE 00000000 __aeabi_unwind_cpp_pr0
Unwind table index '.ARM.exidx' at offset 0x130 contains 1 entries:
0x0 <memcpy_optimized>: 0x80b0b0b0
Compact model 0
0xb0 finish
0xb0 finish
0xb0 finish
Symbol table '.symtab' contains 11 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 SECTION LOCAL DEFAULT 1
2: 00000000 0 SECTION LOCAL DEFAULT 2
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 NOTYPE LOCAL DEFAULT 1 $a
5: 00000000 0 SECTION LOCAL DEFAULT 4
6: 00000000 0 SECTION LOCAL DEFAULT 5
7: 00000000 0 NOTYPE LOCAL DEFAULT 5 $d
8: 00000000 0 SECTION LOCAL DEFAULT 7
9: 00000000 0 FUNC GLOBAL DEFAULT 1 memcpy_optimized
10: 00000000 0 NOTYPE GLOBAL DEFAULT UND __aeabi_unwind_cpp_pr0
No version information found in this file.
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "7-A"
Tag_CPU_arch: v7
Tag_CPU_arch_profile: Application
Tag_ARM_ISA_use: Yes
Tag_THUMB_ISA_use: Thumb-2
Tag_FP_arch: VFPv3
Tag_Advanced_SIMD_arch: NEONv1
Tag_DIV_use: Not allowed
It seems to me that you compiled your foo.c as C++, hence the linking error. What made me say that is that the linker reported the full prototype of the missing function. C functions do not have their full prototype as their symbol (just the name of function), however the C++ mangled names represent the full prototype of the function.
In many Unix and GCC C implementations, names in C are decorated with an initial underscore in object code. So, to call memcpy_optimized in C, you must use the name _memcpy_optimized in assembly.

objdump won't show my ELF sections

I have a tool emitting an ELF, which as far as I can tell is compliant to the spec. Readelf output looks fine, but objdump refuses to disassemble anything.
I have simplified the input to a single global var, and "int main(void) { return 0;}" to aid debugging - the tiny section sizes are correct.
In particular, objdump seems unable to find the sections table:
$ arm-none-linux-gnueabi-readelf -S davidm.elf
There are 4 section headers, starting at offset 0x74:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text NULL ff000000 000034 00001c 00 AX 0 0 4
[ 2] .data NULL ff00001c 000050 000004 00 WA 0 0 4
[ 3] .shstrtab NULL 00000000 000114 000017 00 0 0 0
$ arm-none-linux-gnueabi-objdump -h davidm.elf
davidm.elf: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
I also have another ELF, built from the exact same objects, only produced with regular toolchain use:
$ objdump -h kernel.elf
kernel.elf: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000001c ff000000 ff000000 00008000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000004 ff00001c ff00001c 0000801c 2**2
CONTENTS, ALLOC, LOAD, DATA
Even after I stripped .comment and .ARM.attributes sections (incase objdump requires them) from the 'known good' kernel.elf, it still happily lists the sections there, but not in my tool's davidm.elf.
I have confirmed the contents of the sections are identical between the two with readelf -x.
The only thing I can image is that the ELF file layout is different and breaks some expectations of BFD, which could explain why readelf (and my tool) processes it just fine but objdump has troubles.
Full readelf:
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0xff000000
Start of program headers: 84 (bytes into file)
Start of section headers: 116 (bytes into file)
Flags: 0x5000002, has entry point, Version5 EABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 1
Size of section headers: 40 (bytes)
Number of section headers: 4
Section header string table index: 3
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text NULL ff000000 000034 00001c 00 AX 0 0 4
[ 2] .data NULL ff00001c 000050 000004 00 WA 0 0 4
[ 3] .shstrtab NULL 00000000 000114 000017 00 0 0 0
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000034 0xff000000 0xff000000 0x00020 0x00020 RWE 0x8000
Section to Segment mapping:
Segment Sections...
00 .text .data
There is no dynamic section in this file.
There are no relocations in this file.
There are no unwind sections in this file.
No version information found in this file.
Could the aggressive packing of the on-disk layout be causing troubles? Am I in violation of some bytestream alignment restrictions BFD expects, documented or otherwise?
Lastly - this file is not intended to be mmap'd into an address space, a loader will memcpy segment data into the desired location, so there is no requirement to play mmap-friendly file-alignment tricks. Keeping the ELF small is more important.
Cheers,
DavidM
EDIT: I was asked to upload the file, and/or provide 'objdump -x'. So I've done both:
davidm.elf
$ objdump -x davidm.elf
davidm.elf: file format elf32-littlearm
davidm.elf
architecture: arm, flags 0x00000002:
EXEC_P
start address 0xff000000
Program Header:
LOAD off 0x00000034 vaddr 0xff000000 paddr 0xff000000 align 2**15
filesz 0x00000020 memsz 0x00000020 flags rwx
private flags = 5000002: [Version5 EABI] [has entry point]
Sections:
Idx Name Size VMA LMA File off Algn
SYMBOL TABLE:
no symbols
OK - finally figured it out.
After building and annotating/debugging libbfd (function elf_object_p()) in the context of a little test app, I found why it was not matching on any of BFD supported targets.
I had bad sh_type flags for the section headers: NULL. Emitting STRTAB or PROGBITS (and eventually NOBITS when I get that far) as appropriate and objdump happily walks my image.
Not really surprising, in retrospect - I'm more annoyed I didn't catch this in comparing readelf outputs than anything else :(
Thanks for the help all :)

Resources