2016-04-01 27 views
5

che sto cercando di fare un mondo ciao in architettura ARM con CMake con this toolchainbraccio-nessuno-EABI-gcc con cmake non ha punto di ingresso con la bandiera -nostdlib

mio main.c

int main() 
{ 
    char *str = "Hello World"; 
    return 0; 
} 

E il mio CMakeLists.txt

cmake_minimum_required(VERSION 3.4) 
SET(PROJ_NAME arm-hello-world-nostdlib) 
PROJECT(${PROJ_NAME}) 

# Include directories with headers 
#---------------------------------------------------# 
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) 

# Source 
#---------------------------------------------------# 
FILE(GLOB ${PROJ_NAME}_SRC 
    "src/*.c" 
) 
FILE(GLOB ${PROJ_NAME}_HEADERS 
    "include/*.h" 
) 

# Create Exe 
#---------------------------------------------------# 
ADD_EXECUTABLE(${PROJ_NAME} ${${PROJ_NAME}_SRC} ${${PROJ_NAME}_HEADERS}) 

# Specify libraries or flags to use when linking a given target. 
#---------------------------------------------------# 
TARGET_LINK_LIBRARIES(${PROJ_NAME} -nostdlib --specs=rdimon.specs -lm -lrdimon) 

Questo lancio di configurazione l'avvertimento:

[100%] Linking C executable arm-hello-world-nostdlib 
/usr/lib/gcc/arm-none-eabi/5.2.0/../../../../arm-none-eabi/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000008000 

ed eseguendo il binario con QEMU in crash l'esecuzione:

qemu-arm arm-hello-world-nostdlib 
qemu: uncaught target signal 4 (Illegal instruction) - core dumped 
Illegal instruction (core dumped) 

Senza bandiera --nostdlib funziona perfettamente, e il comando

arm-none-eabi-objdump -s arm-hello-world-nostdlib 

mostrare un sacco di informazioni in formato binario, la compilazione con il flag solo spettacolo:

samples/helloworld-nostdlib/arm-hello-world-nostdlib:  file format elf32-littlearm 

Contents of section .text: 
8000 80b483b0 00af044b 7b600023 18460c37 .......K{`.#.F.7 
8010 bd465df8 047b7047 1c800000   .F]..{pG....  
Contents of section .rodata: 
801c 48656c6c 6f20576f 726c6400   Hello World.  
Contents of section .comment: 
0000 4743433a 20284665 646f7261 20352e32 GCC: (Fedora 5.2 
0010 2e302d33 2e666332 33292035 2e322e30 .0-3.fc23) 5.2.0 
0020 00         .    
Contents of section .ARM.attributes: 
0000 41380000 00616561 62690001 2e000000 A8...aeabi...... 
0010 05436f72 7465782d 4d340006 0d074d09 .Cortex-M4....M. 
0020 020a0612 04140115 01170318 0119011a ................ 
0030 011b011c 011e0622 01     .......".  

Non voglio librerie STL nel mio binario, ma credo di mancare il codice assembly per trovare la voce p mista. Come può aggiungerlo manualmente?

Aggiornamento: Secondo GNU Linker doc per -nostdlib:

Non utilizzare i file di avvio del sistema standard o librerie quando di collegamento. Nessun file di avvio e solo le librerie specificate saranno passate al linker e le opzioni che specificano il collegamento delle librerie del sistema , come -static-libgcc o -shared-libgcc, vengono ignorate.

In alternativa, se qualcuno non desidera la libreria standard utente, può utilizzare flag -nodefaultlibs.

Non utilizzare le librerie di sistema standard durante il collegamento. Solo le librerie specificate vengono passate al linker e le opzioni che specificano il collegamento delle librerie di sistema, come -static-libgcc o -shared-libgcc, vengono ignorate. I file di avvio standard vengono normalmente utilizzati, a meno che non vengano utilizzati -nostartfiles.

Il compilatore può generare chiamate a memcmp, memset, memcpy e memmove. Queste voci sono generalmente risolte dalle voci in libc. Questi punti devono essere forniti attraverso qualche altro meccanismo quando viene specificata l'opzione .

A proposito, voglio un modo per creare e aggiungere i file di avvio, una possibile via di this tutorial, ma aggiungo la bontà di ottenere una risposta alla mia domanda e hanno una soluzione generale per tutti. Considero questo utile per le persone che vogliono personalizzare e conoscere i file crosscompilation, arm e startup.

Aggiornamento 2

Utilizzando inizio.S codice assembly:

.text 
.align 4 

.global _start 
.global _exit 

_start: 
     mov  fp, #0    /* frame pointer */ 
     ldr  a1, [sp]    /* 1st arg = argc */ 
     add  a2, sp, #4   /* 2nd arg = argv */ 

     bl  main 

_exit: 
     mov  r7, #1    /* __NR_exit */ 
     swi  0 

.type _start,function 
.size _start,_exit-_start 

.type _exit,function 
.size _exit,.-_exit 

per indicare il punto di ingresso fornita da ARSV e compilare utilizzando il comando:

arm-none-eabi-gcc -nostdlib -o main main.c start.S 

sembra funzionare propertly. Aggiornamento di CMakeLists.txt:

#Directly works: 
#arm-none-eabi-gcc -nostdlib -o main main.c start.S 

cmake_minimum_required(VERSION 3.4) 
SET(PROJ_NAME arm-hello-world-nostdlib) 

# Assembler files (.S) in the source list are ignored completely by CMake unless we 
# “enable” the assembler by telling CMake in the project definition that we’re using assembly 
# files. When we enable assembler, CMake detects gcc as the assembler rather than as – this 
# is good for us because we then only need one set of compilation flags. 
PROJECT(${PROJ_NAME} C ASM) 

# Include directories with headers 
#---------------------------------------------------# 
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) 

# Source 
#---------------------------------------------------# 
FILE(GLOB ${PROJ_NAME}_SRC 
    "src/start.S" 
    "src/*.c" 
) 
FILE(GLOB ${PROJ_NAME}_HEADERS 
    "include/*.h" 
) 

# Create Exe 
#---------------------------------------------------# 
ADD_EXECUTABLE(${PROJ_NAME} ${${PROJ_NAME}_SRC} ${${PROJ_NAME}_HEADERS}) 

# Specify libraries or flags to use when linking a given target. 
#---------------------------------------------------# 
TARGET_LINK_LIBRARIES(${PROJ_NAME} -nostdlib --specs=rdimon.specs -lm -lrdimon) 

Se si ottiene collegando i problemi come:

arm-none-eabi/bin/ld: error: CMakeFiles/arm-hello-world-nostdlib.dir/src/main.c.obj: Conflicting CPU architectures 1/13 

E 'un problema con toolchain, per Cortex-A9, funziona utilizzando:

set(CMAKE_C_FLAGS 
    "${CMAKE_C_FLAGS}" 
    "-mcpu=cortex-a9 -march=armv7-a -mthumb" 
    "-mfloat-abi=softfp -mfpu=fpv4-sp-d16" 
) 
+3

STL è C++, perché dovresti averlo nel tuo programma C? Tecnicamente è possibile impostare il punto di ingresso su main nel comando linker, ma questo salta la fase di inizializzazione di libc e quindi non è raccomandato. – Jester

+0

Senza crosscompile, seguendo questo tutorial: https://blogs.oracle.com/ksplice/entry/hello_from_a_libc_free, funziona perfettamente, perché usa il proprio file di assemblaggio _start stub, che funziona in x86. Presumo che ho bisogno di qualcosa di simile in ARM, ma non so cosa usare, lo stesso file di assembly non funziona perché l'architettura è diversa. – vgonisanz

+0

Si noti che l'articolo collegato in particolare non utilizza la libreria C. Che funzioni. Ciò che non è garantito funziona è il mix di '-nostdlib' con' -lc'.Dovresti decidere se hai bisogno di libc, nel qual caso non usi '-nostdlib', o se non ti serve, allora non usare' -lc' e imposta il punto di ingresso tramite l'opzione linker. – Jester

risposta

3

Ecco _start .s Io uso in un mio piccolo progetto.
Dovrebbe essere sufficiente per collegare e gestire il main() con QEMU-braccio:

.text 
.align 4 

.global _start 
.global _exit 

_start: 
     mov  fp, #0    /* frame pointer */ 
     ldr  a1, [sp]    /* 1st arg = argc */ 
     add  a2, sp, #4   /* 2nd arg = argv */ 

     bl  main 

_exit: 
     mov  r7, #1    /* __NR_exit */ 
     swi  0 

.type _start,function 
.size _start,_exit-_start 

.type _exit,function 
.size _exit,.-_exit 

notare che questo è il codice di avvio per comune userspace binario Linux su ARM. Che è quello che probabilmente vuoi per qemu-arm (qemu linux-user mode o syscall proxy). Per altri casi, come i binari bare iron nel post collegato, o lo spazio utente non Linux, o altre architetture, il codice di avvio sarà diverso.

In Linux, un binario appena caricato viene richiamato con argc in cima allo stack, seguito da argv [], seguito da envp [], seguito da auxv []. Il codice di avvio deve trasformarlo in una corretta chiamata principale (argc, argv) in base alla convenzione di chiamata dell'arco. Per ARM è il primo argomento nel registro a1, il secondo in a2.

"Viene richiamato" sopra significa un salto all'indirizzo e_entry dall'intestazione ELF, che viene impostato da ld per puntare a _start simbolo se ne viene trovato uno. Senza _start definito da nessuna parte, ld imposta e_entry su 0x8000 e qualsiasi cosa accadesse a 0x8000 quando il jump è stato fatto apparentemente non sembra un'istruzione ARM valida. Che non è esattamente inaspettato

Leggere il codice da implementazioni di libc più piccole/più pulite come musl o dietlibc aiuta molto nella comprensione di cose come questa. A proposito, il codice di cui sopra deriva da dietlibc.

https://github.com/ensc/dietlibc/blob/master/arm/start.S
http://git.musl-libc.org/cgit/musl/tree/arch/arm/crt_arch.h

Per riferimento, CMakeLists.txt minimalista per generare il progetto:
(assumendo che i file sono denominati main.ce _start.s)

project(arm-hello-world-nostdlib) 
cmake_minimum_required(VERSION 3.4) 

enable_language(ASM) 
set(CMAKE_C_COMPILER arm-none-gnueabi-gcc) 
set(CMAKE_ASM_COMPILER arm-none-gnueabi-gcc) 
set(CMAKE_ASM_FLAGS -c) 
set(CMAKE_VERBOSE_MAKEFILE on) 

add_executable(main _start.s main.c) 
target_link_libraries(main -nostdlib) 

Eseguire il conseguente eseguibile come questo: qemu-arm ./main

+0

Ok. Il tuo codice assembly sembra funzionare manualmente. "arm-none-eabi-gcc -nostdlib start.S -o main main.c" e "qemu-arm main" funzionano bene con informazioni minime in "arm-none-eabi-objdump main". Per completare la risposta, avrò bisogno di sapere come farlo funzionare su CMakeLists.txt, perché non posso aggiungere il file start.S nel codice o il flag di collegamento per farlo funzionare con CMake. – vgonisanz

+0

Non è un grande fan di cmake, in parte a causa di cose come questa. A quanto pare è necessario abilitare il linguaggio ASM, altrimenti silenziosamente ignora i file assembly. L'esempio di CMakeLists.txt aggiunto, sembra funzionare per me – arsv

+0

Bene, grazie, sembra che la tua proposta sia valida. Sto cercando di fare lo stesso, ma ho un problema sconosciuto con il linker, ma è una soluzione valida, 15 ore per assegnare la taglia :-p – vgonisanz

Problemi correlati