0

I have a .obj file that is created by ml64 and then used by a vsxproj to compile a windows dll. The C part simply acts as a pass-through to one function in the masm code.

Is it possible to do the same with gcc so I can compile a linux .so file?

Edit:

objdump -f test.obj returns:

test.obj :
file format pe-x86-64
architecture: i386:x86-64, flags 0x0000003d :
HAS RELOC, HAS LINENO, HAS DEBUG, HAS SYMS, HAS LOCALS
start address 0X0000000000000000

Trying objcopy -I pe-x86-64 -O elf64-x86-64 test.obj test.o gives :

objcopy: test.o: (null)unsupported
objcopy: test.o: sorry, cannot handle this file

Edit2: gcc output:

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.3.0-1ubuntu1~22.04' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-11-xKiWfi/gcc-11-11.3.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-11-xKiWfi/gcc-11-11.3.0/debian/tmp-gcn/usr --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.3.0 (Ubuntu 11.3.0-1ubuntu1~22.04) 
COLLECT_GCC_OPTIONS='-v' '-shared' '-o' 'EmulatorCore.so' '-fPIC' '-Wall' '-g' '-m64' '-mtune=generic' '-march=x86-64' '-dumpdir' 'EmulatorCore.so-'
 /usr/lib/gcc/x86_64-linux-gnu/11/cc1 -quiet -v -imultiarch x86_64-linux-gnu core.c -quiet -dumpdir EmulatorCore.so- -dumpbase core.c -dumpbase-ext .c -m64 -mtune=generic -march=x86-64 -g -Wall -version -fPIC -fasynchronous-unwind-tables -fstack-protector-strong -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccNiOQu1.s
GNU C17 (Ubuntu 11.3.0-1ubuntu1~22.04) version 11.3.0 (x86_64-linux-gnu)
    compiled by GNU C version 11.3.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version isl-0.24-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/11/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/11/include
 /usr/local/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
GNU C17 (Ubuntu 11.3.0-1ubuntu1~22.04) version 11.3.0 (x86_64-linux-gnu)
    compiled by GNU C version 11.3.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version isl-0.24-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 3f6cb05d963ad324b8f9442822c95179
COLLECT_GCC_OPTIONS='-v' '-shared' '-o' 'EmulatorCore.so' '-fPIC' '-Wall' '-g' '-m64' '-mtune=generic' '-march=x86-64' '-dumpdir' 'EmulatorCore.so-'
 as -v --gdwarf-5 --64 -o /tmp/ccs6mQj9.o /tmp/ccNiOQu1.s
GNU assembler version 2.38 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.38
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-shared' '-o' 'EmulatorCore.so' '-fPIC' '-Wall' '-g' '-m64' '-mtune=generic' '-march=x86-64' '-dumpdir' 'EmulatorCore.so.'
 /usr/lib/gcc/x86_64-linux-gnu/11/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/11/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper -plugin-opt=-fresolution=/tmp/cc2PLxAY.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -shared -z relro -o EmulatorCore.so /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/11/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/11 -L/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/11/../../.. /tmp/ccs6mQj9.o core.obj -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/11/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/crtn.o
COLLECT_GCC_OPTIONS='-v' '-shared' '-o' 'EmulatorCore.so' '-fPIC' '-Wall' '-g' '-m64' '-mtune=generic' '-march=x86-64' '-dumpdir' 'EmulatorCore.so.'

I'm using a simple wrapper to adjust to the calling convention

#include <stdint.h>

extern int32_t asm_func(void* state);

int wrapper(void *state)
{
  int32_t toReturn = 0;

  __asm__ volatile(
     "mov %rdi, %rsi \t\n"
     "call asm_func  \t\n");

  return toReturn;
}

int32_t fnEmulatorCode(void* state) {
  return wrapper(state);
}
BJury
  • 2,526
  • 3
  • 16
  • 27
  • It appears that you can using `gcc -shared output.so -fPIC test.c test.obj` however the resulting code doesn't handle relocation problem, so it _partially_ works.. – BJury Apr 24 '23 at 18:03
  • Can you add (to your question) the complete output of the command `gcc -v` that you are using to link this on Linux? It should also be noted (in the absence of code) that even if you get this working the calling convention is different in Linux than Windows. The volatile registers are different, and the registers to pass variables into a function are different. There is no shadow stack on 64-bit Linux but there is on Windows, and there are stack alignment requirements on Linux. – Michael Petch Apr 24 '23 at 20:40
  • @MichaelPetch Thanks for looking, I've pasted the gcc output. The calling convention is handled in a wrapper, and the function itself is entirely contained, so there should be no problems on that front. It does run, its just the jump tables aren't adjusted, so I'm missing a step somewhere... – BJury Apr 24 '23 at 22:13

1 Answers1

0

The answer is you just can.

The problems experienced were from the code not being relocated properly.

BJury
  • 2,526
  • 3
  • 16
  • 27