Compatability of cross-built COFF files and MSVS - c

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?

Related

Name mangling in MASM (ML64) is inconsistent

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

relationship between VMA and ELF segments

I need to determine the VMAs for loadable segments of ELF executables. VMAs can be printed from /proc/pid/maps. The relationship between VMAs shown by maps with loadable segments is also clear to me. Each segment consists of one or more VMAs. what is the method used by kernel to form VMAs from ELF segments: whteher it takes into consideration only permissions/flags or something else is also required? As per my understanding, a segment with flags Read, Execute(code) will go in separate VMA having same permission. While next segment with permissions Read, Write(data) should go in an other VMA. But this is not case with second loadable segment, it is usually splitted in two or more VMAs: some with read and write while other with read only. So My assumption that flags are the only culprit for VMA generation seems wrong. I need help to understand this relationship between segments and VMAs.
What I want to do is to programmatically determine the VMAs for loadable segments of ELF with out loading it in memory. So any pointer/help in this direction is the main objective of this post.
A VMA is a homogeneous region of virtual memory with:
the same permissions (PROT_EXEC, etc.);
the same type (MAP_SHARED/MAP_PRIVATE);
the same backing file (if any);
a consistent offset within the file.
For example, if you have a VMA which is RW and you mprotect PROT_READ (you remove the permission to write) a part in the middle of the VMA, the kernel will split the VMA in three VMAs (the first one being RW, the second R and the last RW).
Let's look at a typical VMA from an executable:
$ cat /proc/$$/maps
00400000-004f2000 r-xp 00000000 08:01 524453 /bin/bash
006f1000-006f2000 r--p 000f1000 08:01 524453 /bin/bash
006f2000-006fb000 rw-p 000f2000 08:01 524453 /bin/bash
006fb000-00702000 rw-p 00000000 00:00 0
[...]
The first VMA is the text segment. The second, third and fourth VMAs are the data segment.
Anonymous mapping for .bss
At the beginning of the process, you will have something like this:
$ cat /proc/$$/maps
00400000-004f2000 r-xp 00000000 08:01 524453 /bin/bash
006f1000-006fb000 rw-p 000f1000 08:01 524453 /bin/bash
006fb000-00702000 rw-p 00000000 00:00 0
[...]
006f1000-006fb000 is the part of the text segment which comes from the executable file.
006fb000-00702000 is not present in the executable file because it is initially filled with zeroes. The non-initialized variables of the process are all grouped together (in the .bss segment) and are not represented in the executable file in order to save space (1).
This come from the PT_LOAD entries of the program header table of the executable file (readelf -l) which describe the segments to map into memory:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
[...]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000f1a74 0x00000000000f1a74 R E 200000
LOAD 0x00000000000f1de0 0x00000000006f1de0 0x00000000006f1de0
0x0000000000009068 0x000000000000f298 RW 200000
[...]
If you look at the corresponding PT_LOAD entry, you will notice that a part of the the segment is not represented in the file (because the file size is smaller than the memory size).
The part of the data segment which is not in the executable file is initialized with zeros: the dynamic linker uses a MAP_ANONYMOUS mapping for this part of the data segment. This is why is appears as a separate VMA (it does not have the same backing file).
Relocation protection (PT_GNU_RELRO)
When the dynamic, linker has finished doing the relocations (2), it might mark some part of the data segment (the .got section among others) as read-only in order to avoid GOT-poisoning attacks or bugs. The section of the data segment which should be protected after the relocations in described by the PT_GNU_RELRO entry of the program header table: the dynamic linker mprotect(addr, len, PROT_READ) the given region after finishing the relocations (3). This mprotect call splits the second VMA in two VMAs (the first one R and the second one RW).
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
[...]
GNU_RELRO 0x00000000000f1de0 0x00000000006f1de0 0x00000000006f1de0
0x0000000000000220 0x0000000000000220 R
[...]
Summary
The VMAs
00400000-004f2000 r-xp 00000000 08:01 524453 /bin/bash
006f1000-006f2000 r--p 000f1000 08:01 524453 /bin/bash
006f2000-006fb000 rw-p 000f2000 08:01 524453 /bin/bash
006fb000-00702000 rw-p 00000000 00:00 0
are derived from the VirtAddr, MemSiz and Flags fields of the PT_LOAD and PT_GNU_RELRO entries:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
[...]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000f1a74 0x00000000000f1a74 R E 200000
LOAD 0x00000000000f1de0 0x00000000006f1de0 0x00000000006f1de0
0x0000000000009068 0x000000000000f298 RW 200000
[...]
GNU_RELRO 0x00000000000f1de0 0x00000000006f1de0 0x00000000006f1de0
0x0000000000000220 0x0000000000000220 R
[...]
First all PT_LOAD entries are processes. Each of them triggers the creation of one VMA by using a mmap(). In addition, if MemSiz > FileSiz, it might create an additional anonymous VMA.
Then all (well there is only once in pratice) PT_GNU_RELRO are processes. Each of them triggers a mprotect() call which might split an existing VMA into different VMAs.
In order to do what you want, the correct way is probably to simulate the mmap and mprotect calls:
// Virtual Memory Area:
struct Vma {
std::uint64_t addr, length;
std::string file_name;
int prot;
int flags;
std::uint64_t offset;
};
// Virtual Address Space:
class Vas {
private:
std::list<Vma> vmas_;
public:
Vma& mmap(
std::uint64_t addr, std::uint64_t length, int prot,
int flags, int fd, off_t offset);
int mprotect(std::uint64_t addr, std::uint64_t len, int prot);
std::list<Vma> const& vmas() const { return vmas_; }
};
for (Elf32_Phdr const& h : phdrs)
if (h.p_type == PT_LOAD) {
vas.mmap(...);
if (anon_size)
vas.mmap(...);
}
for (Elf32_Phdr const& h : phdrs)
if (h.p_type == PT_GNU_RELRO)
vas.mprotect(...);
Some examples of computations
The addresses are slightly different because the VMAs are page-aligned (3) (using 4Kio = 0x1000 pages for x86 and x86_64):
The first VMA is describes by the first PT_LOAD entry:
vma[0].start = page_floor(load[0].virt_addr)
= 0x400000
vma[0].end = page_ceil(load[1].virt_addr + load[1].phys_size)
= page_ceil(0x400000 + 0xf1a74)
= page_ceil(0x4f1a74)
= 0x4f2000
The next VMA is the part of the data segment which as been protected and is described by PT_GNU_RELRO:
vma[1].start = page_floor(relro[0].virt_addr)
= page_floor(0xf1de0)
= 0x6f1000
vma[1].end = page_ceil(relro[0].virt_addr + relo[0].mem_size)
= page_ceil(0x6f1de0 + 0x220)
= page_ceil(0x6f2000)
= 0x6f2000
[...]
Correspondence with the sections
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 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.ABI-tag NOTE 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4
[ 3] .note.gnu.build-i NOTE 0000000000400274 00000274
0000000000000024 0000000000000000 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000400298 00000298
0000000000004894 0000000000000000 A 5 0 8
[ 5] .dynsym DYNSYM 0000000000404b30 00004b30
000000000000d6c8 0000000000000018 A 6 1 8
[ 6] .dynstr STRTAB 00000000004121f8 000121f8
0000000000008c25 0000000000000000 A 0 0 1
[ 7] .gnu.version VERSYM 000000000041ae1e 0001ae1e
00000000000011e6 0000000000000002 A 5 0 2
[ 8] .gnu.version_r VERNEED 000000000041c008 0001c008
00000000000000b0 0000000000000000 A 6 2 8
[ 9] .rela.dyn RELA 000000000041c0b8 0001c0b8
00000000000000c0 0000000000000018 A 5 0 8
[10] .rela.plt RELA 000000000041c178 0001c178
00000000000013f8 0000000000000018 AI 5 12 8
[11] .init PROGBITS 000000000041d570 0001d570
000000000000001a 0000000000000000 AX 0 0 4
[12] .plt PROGBITS 000000000041d590 0001d590
0000000000000d60 0000000000000010 AX 0 0 16
[13] .text PROGBITS 000000000041e2f0 0001e2f0
0000000000099c42 0000000000000000 AX 0 0 16
[14] .fini PROGBITS 00000000004b7f34 000b7f34
0000000000000009 0000000000000000 AX 0 0 4
[15] .rodata PROGBITS 00000000004b7f40 000b7f40
000000000001ebb0 0000000000000000 A 0 0 64
[16] .eh_frame_hdr PROGBITS 00000000004d6af0 000d6af0
000000000000407c 0000000000000000 A 0 0 4
[17] .eh_frame PROGBITS 00000000004dab70 000dab70
0000000000016f04 0000000000000000 A 0 0 8
[18] .init_array INIT_ARRAY 00000000006f1de0 000f1de0
0000000000000008 0000000000000000 WA 0 0 8
[19] .fini_array FINI_ARRAY 00000000006f1de8 000f1de8
0000000000000008 0000000000000000 WA 0 0 8
[20] .jcr PROGBITS 00000000006f1df0 000f1df0
0000000000000008 0000000000000000 WA 0 0 8
[21] .dynamic DYNAMIC 00000000006f1df8 000f1df8
0000000000000200 0000000000000010 WA 6 0 8
[22] .got PROGBITS 00000000006f1ff8 000f1ff8
0000000000000008 0000000000000008 WA 0 0 8
[23] .got.plt PROGBITS 00000000006f2000 000f2000
00000000000006c0 0000000000000008 WA 0 0 8
[24] .data PROGBITS 00000000006f26c0 000f26c0
0000000000008788 0000000000000000 WA 0 0 64
[25] .bss NOBITS 00000000006fae80 000fae48
00000000000061f8 0000000000000000 WA 0 0 64
[26] .shstrtab STRTAB 0000000000000000 000fae48
00000000000000ef 0000000000000000 0 0 1
It you compare the Address of the sections (readelf -S) with the ranges of the VMAs, you find the mappings:
00400000-004f2000 r-xp /bin/bash : .interp, .note.ABI-tag, .note.gnu.build-id, .gnu.hash, .dynsym, .dynstr, .gnu.version, .gnu.version_r, .rela.dyn, .rela.plt, .init, .plt, .text, .fini, .rodata.eh_frame_hdr, .eh_frame
006f1000-006f2000 r--p /bin/bash : .init_array, .fini_array, .jcr, .dynamic, .got
006f2000-006fb000 rw-p /bin/bash : .got.plt, .data, beginning of .bss
006fb000-00702000 rw-p - : rest of .bss
Notes
(1): In fact, its more complicated: a part of the .bss section might be represented in the executable file for page alignment reasons.
(2): In fact, when it has finished doing the non-lazy relocations.
(3): MMU operations are using the page-granularity so the memory ranges of mmap(), mprotect(), munmap() calls are extended to cover full-pages.

Interpreting ELF symbol table

I wrote a simple program called a.c to understand the symbol table on x86 machine:
extern int foo;
int function(void){
return foo;
}
I compile it and readelf
$gcc -c -m32 a.c
$readelf -a a.o > a.log
The symbol table in a.log is shown below:
Symbol table '.symtab' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS a.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 6
6: 00000000 0 SECTION LOCAL DEFAULT 7
7: 00000000 0 SECTION LOCAL DEFAULT 5
8: 00000000 10 FUNC GLOBAL DEFAULT 1 function
9: 00000000 0 NOTYPE GLOBAL DEFAULT UND foo
What are the purpose of symbol table entry 0 and entries from 2 to 7?

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.

c code reports undef sprintf in dumpbin Compiles no error

I have c code that compiles and links fine on another PC. I am tring now to get everything to work on my Windows 7 64 bit OS. The Code compiles into a object with no errors however when I run dumpbin on the object with /SYMBOLS I get several UNDEF messages.
0F9 00000000 UNDEF notype External | __imp__sprintf
0FA 00000000 UNDEF notype External | __imp__fclose
0FB 00000000 UNDEF notype External | __imp__fopen
0FC 00000008 SECT3 notype Static | _i
0FD 00000000 UNDEF notype () External | _strcmp
0FE 00000000 UNDEF notype External | __imp__setlocale
0FF 00000000 UNDEF notype () External | _strcpy
100 00000290 SECT5 notype () Static | _f_read_common_fields
101 00000000 UNDEF notype () External | _memcpy
102 00000000 UNDEF notype External | __imp__fread
103 00000000 UNDEF notype () External | _memset
104 00000000 UNDEF notype External | ___security_cookie
105 00000000 UNDEF notype () External | #__security_check_cookie#4
Seems like I am just message a path statement or something but can not find it. This is all external code (Not in a VS Project) using VS2005 to compile from the command line.
It looks like a linker problem. I see your compile line, but what about the link line. Off the top of my head I can't remember the VC library for standard c stuff.
Is it msvcrt.lib? Are you including that on the link line?

Resources