I have the following headers and source files:
AVR_comunic.h
#ifndef AVR_COMUNIC_H_
#define AVR_COMUNIC_H_
#include<avr/io.h>
#define FOSC 20000000UL // Clock Speed
#define BAUD 19200
#define MYUBRR FOSC/16/BAUD-1
void USART_Init( unsigned int);
int USART_WriteChar(unsigned char);
// int USART_Receive( unsigned char *);
void USART_Flush(void);
#endif /* AVR_COMUNIC_H_ */
AVR_comunic.c
#include "AVR_comunic.h"
void USART_Flush( void )
{
...
}
void USART_Init( unsigned int ubrr)
{
...
}
int USART_WriteChar(unsigned char data)
{
...
}
and main_f.c
#include"AVR_comunic.h"
void init_ports()
{
DDRD|= (1<<PD7);
}
int main(void)
{
init_ports();
...
while(1)
{
// now what?
}
return 1;
}
I wrote a batch file in Notepad++ to obtain the .hex file for this program
COMPILE_BUILD.bat
ECHO OFF
ECHO ----------------------------------------------------------
ECHO ----- executing your commands : compile and build -------
ECHO ----------------------------------------------------------
avr-gcc -g -Wall -Os -DF_CPU=20000000UL -mmcu=atmega88p -c AVR_comunic.c
avr-gcc -g -Wall -Os -DF_CPU=20000000UL -mmcu=atmega88p -c main_f.c
avr-gcc -g -mmcu=atmega88p -o AVR_comunic.elf main_f.o AVR_comunic.o
avr-objdump -h -S AVR_comunic.elf > AVR_comunic.lst
avr-gcc -g -mmcu=atmega8 -Wl,-Map,AVR_comunic.map -o AVR_comunic.elf AVR_comunic.o
avr-objcopy -j .text -j .data -O ihex AVR_comunic.elf AVR_comunic.hex
ECHO ----------------------------------------------------------
ECHO ---------------------- happy ? ---------------------------
ECHO ----------------------------------------------------------
pause
I get the following error:
... : undefined reference to 'main'
avr-objcopy: 'AVR_comunic.elf' no such file
I understand from the information on internet that the linker does thinks that there is no "main" function ... but it is ... what am I doing wrong? Or how should I write to compile multiple source files?
I understand from the information on internet that the linker does thinks that there is no "main" function ... but it is ... what am I doing wrong?
This command:
avr-objdump -h -S AVR_comunic.elf > AVR_comunic.lst
attempts to extract info from AVR_communic.elf, which isn't produced yet. You want to move it after this command:
avr-gcc -g -mmcu=atmega8 -Wl,-Map,AVR_comunic.map -o AVR_comunic.elf AVR_comunic.o
The above command fails with undefined reference to: 'main' because you are not linking main_f.o into it.
It appears that what you really want is:
avr-gcc -g -mmcu=atmega88p -o AVR_communic.elf main_f.o AVR_comunic.o
avr-objdump -h -S AVR_comunic.elf > AVR_comunic.lst
avr-objcopy -j .text -j .data -O ihex AVR_comunic.elf AVR_comunic.hex
Related
So basically, I'm trying to do input with gnu-efi and I've struggled but I finally got something compiling. Here it is:
#include <efi.h>
#include <efilib.h>
EFI_STATUS EFIAPI efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
EFI_STATUS status;
EFI_INPUT_KEY Key;
InitializeLib(ImageHandle, SystemTable);
//status = SystemTable->ConIn->Reset(SystemTable->ConIn, FALSE);
if (EFI_ERROR(status))
return status;
SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello pussy\n");
while((status = SystemTable->ConIn->ReadKeyStroke(SystemTable->ConIn, &Key)) == EFI_NOT_READY && Key.ScanCode != 0x17);
times
return EFI_SUCCESS;
}
My problem is that this causes the process to be stuck on the starting and makes my fans go crazy. There are no errors or anything. It just doesn't work. It stops the process and it makes my fans go overdrive. Any ConIn function does that.
**
Extra info:
**
The make file I compile my code with:
OBJS = main3.o
TARGET = hello3.efi
EFIINC = /usr/include/efi
EFIINCS = -I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol
LIB = /usr/lib64
EFILIB = /usr/lib64/
EFI_CRT_OBJS = $(EFILIB)/crt0-efi-$(ARCH).o
EFI_LDS = $(EFILIB)/elf_$(ARCH)_efi.lds
CFLAGS = -ffreestanding $(EFIINCS) -fno-stack-protector -fpic \
-fshort-wchar -mno-red-zone -Wall -c
ifeq ($(ARCH),x86_64)
CFLAGS += -DEFI_FUNCTION_WRAPPER
endif
LDFLAGS = -nostdlib -znocombreloc -T $(EFI_LDS) -shared \
-Bsymbolic -L $(EFILIB) -L $(LIB) $(EFI_CRT_OBJS)
all: $(TARGET)
main3.o: hello.c
gcc $(CFLAGS) hello3.c -o main3.o
hello3.so: $(OBJS)
ld $(LDFLAGS) $(OBJS) -o $# -lefi -lgnuefi
%.efi: %.so
objcopy -j .text -j .sdata -j .data -j .dynamic \
-j .dynsym -j .rel -j .rela -j .reloc \
--target=efi-app-$(ARCH) $^ $#
the command I run qemu with:
qemu-system-x86_64 -bios OVMF.fd -drive media=disk,id=boot,format=raw,file=fat:rw:DirContainingEFI/BOOT/bootx64.efi,index=0
(I am using Ubuntu 18.04 x86-64)
These are the two source files of my program:
//main.c
#include "stdio.h"
int sum(int *a, int n);
int array[2] = {1, 2};
int main()
{
int val = sum(array,2);
printf("%d\n", val);
return 0;
}
//sum.c
int sum(int *a, int n)
{
int i = 0,s =0;
for(;i<n;i++)
s+=a[i];
return s;
}
I generated the executable by the following steps:
# preprocessing
gcc -E main.c -o main.i
gcc -E sum.c -o sum.i
# compilation
gcc -Og -S main.i -o main.s
gcc -Og -S sum.i -o sum.s
# assembling
as main.s -o main.o
as sum.s -o sum.o
# linking
ld -o prog sum.o main.o -lc --entry main
But prog can not be run:
$ ./prog
-bash: ./prog: No such file or directory
$ file ./prog
prog: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld6, not stripped
$ stat prog
File: prog
Size: 6424 Blocks: 16 IO Block: 4096 regular file
Device: 801h/2049d Inode: 3153139 Links: 1
Access: (0777/-rwxrwxrwx) Uid: ( 1000/ u) Gid: ( 1000/ u)
Access: 2021-01-22 17:41:02.516854257 +0800
Modify: 2021-01-22 17:31:02.969230783 +0800
Change: 2021-01-22 17:40:57.432364965 +0800
Birth: -
I wonder what went wrong that prevents me from executing the file.
If you run ldd prog you will see /lib/ld64.so.1 => /lib64/ld-linux-x86-64.so.2. The loader /lib/ld64.so.1 does not exists and you get a No such file or directory error. If you add --dynamic-linker=/lib64/ld-linux-x86-64.so.2 to your linking options the program can be executed. Also see this answer.
Edit:
You can see the arguments used by gcc by executing gcc -v main.c sum.c -o program. I used that output for finding the missing linking arguments. When linking with ld -o prog sum.o main.o -lc --dynamic-linker=/lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/8/crtbeginS.o -lc /usr/lib/gcc/x86_64-linux-gnu/8/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/crtn.o there was no segmentation anymore.
I have three files in my XV6: testmain.c, foo.h, and foo.c :
foo.h :
extern void myfunction(void)
foo.c:
#include "foo.h"
void myfunction(void){
printf(1, "HelloWorld"); }
testmain.c:
#include "foo.h"
int main(void){
myfunction();
return 0 ; }
I am getting undefined reference error for myfunction() in test_main . I know I need to change something in Makefile for XV6, but I don't know what. that's what I have changed in XV6 Makefile:
UPROGS=\
_cat\
_echo\
_forktest\
_grep\
_init\
_kill\
_ln\
_ls\
_mkdir\
_rm\
_sh\
_stressfs\
_usertests\
_wc\
_zombie\
_foo\
_testmain\
You need several changes in Makefile:
Indicate that you want to create _testmain program,
Tell what _testmain dependencies are (if apply).
add _testmain in programs list:
UPROGS=\
_testmain\
_cat\
_crash\
_echo\
_factor\
....
_testmain dependencies:
Since your _testmain program depends on two files, you must create a special rule telling that to builder (I make this rule from _%: %.o $(ULIB) rule):
_testmain: testmain.o foo.o $(ULIB)
$(LD) $(LDFLAGS) -N -e main -Ttext 0x1000 -o $# $^
$(OBJDUMP) -S $# > $*.asm
$(OBJDUMP) -t $# | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $*.sym
I have the following test setup below. When I compile the code, I get the following error: The initUSART is not recognized, but I have included the file in the appropriate places. Did I miss out on anything?
AVR Development Stack
Get input main.c file...
Compile code and return elf file...
main.o: In function `main':
/Users/sebastianscharf/Documents/Hardware/AVR/main.c:14: undefined reference to `initUSART'
collect2: error: ld returned 1 exit status
avr-objcopy: 'main.elf': No such file
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: Expected signature for ATmega328 is 1E 95 14
Double check chip, or use -F to override this check.
avrdude done. Thank you.
main file
#include "config.h"
#include <avr/io.h>
#include <util/delay.h>
#include "USART.h"
int main(void) {
char serialCharacter;
// --- INITS --- //
DDRB = 0xff;
// Set up LED for output
initUSART();
return 0;
}
USART.h
/* These are defined for convenience */
#define USART_HAS_DATA bit_is_set(UCSR0A, RXC0)
#define USART_READY bit_is_set(UCSR0A, UDRE0)
uint8_t receiveByte(void);
/* Takes the defined BAUD and F_CPU, calculates the bit-clock multiplier, and configures the hardware USART*/
void initUSART(void);
USART.c
#include "config.h"
#include <avr/io.h>
#include <util/setbaud.h>
#include "USART.h"
void initUSART(void) {
// Requires BAUD
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= (1 << U2X0);
#else
UCSR0A &= ~(1 << U2X0);
#endif
// Enable USART
UCSR0B = (1 << TXEN0) | (1 << RXEN0);
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8 data bits, 1 stop bit
}
bash file
#!/bin/bash
source bashColors.sh
echo -e "${IGreen}AVR Development Stack${Reset}"
echo -e "${BIBlue}Get input main.c file...${Reset}"
avr-gcc -g -Os -mmcu=atmega328p -c main.c USART.c &&
echo -e "${BIBlue}Compile code and return elf file...${Reset}"
avr-gcc -g -mmcu=atmega328p -o main.elf main.o &&
echo -e "${BIBlue}Convert elf file to hex...${Reset}"
# avr-objcopy converts into hex file. -j indicates that we want the information from the .text and .data segment extracted.
avr-objcopy -j .text -j .data -O ihex main.elf out.hex &&
echo -e "${BIBlue}Uploading data to microcontroller...${Reset}"
avrdude -c usbtiny -p m328
You compiled both source files properly to .o with:
avr-gcc -g -Os -mmcu=atmega328p -c main.c USART.c
Now the main.o file contains an external reference to initUSART (partly thanks to the #include "USART.h" directive which provides the proper prototype)
but this link line:
avr-gcc -g -mmcu=atmega328p -o main.elf main.o &&
only references main.o. You need to add USART.o so the symbol is resolved by the linker (the linker doesn't care about .h include files), like this:
avr-gcc -g -mmcu=atmega328p -o main.elf main.o USART.o &&
I'm working my way through The Little Book About OS Development, specifically the section on the framebuffer (linked). I'm able to successfully assemble, link, turn into an ISO file and boot pure assembly, but as soon as I try to link a compiled object file for my C code (called from my loader, which was written in assembly), the linker complains. Here's the output:
nasm -f elf loader.s -o loader.o
nasm -f elf out.s -o out.o
/usr/local/Cellar/gcc#6/6.4.0/bin/gcc-6 -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs -Wall -Wextra -Werror -c framebuffer.c -o framebuffer.o
/usr/local/Cellar/gcc#6/6.4.0/bin/gcc-6 -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs -Wall -Wextra -Werror -c kmain.c -o kmain.o
i386-unknown-linux-gnu-ld -T link.ld -melf_i386 loader.o out.o framebuffer.o kmain.o -o kernel.elf
framebuffer.o: file not recognized: File format not recognized
make: *** [kernel.elf] Error 1
I'm on a Mac, so as you can tell I've compiled a custom version of the GNU linker so that I can use linker scripts, and I've made sure to specify GCC 6 (the system default is 4.0). Anyway, here's my Makefile:
OBJECTS = loader.o out.o framebuffer.o kmain.o
CC = /usr/local/Cellar/gcc#6/6.4.0/bin/gcc-6
CFLAGS = -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector \
-nostartfiles -nodefaultlibs -Wall -Wextra -Werror -c
LDFLAGS = -T link.ld -melf_i386
AS = nasm
ASFLAGS = -f elf
all: kernel.elf
kernel.elf: $(OBJECTS)
i386-unknown-linux-gnu-ld $(LDFLAGS) $(OBJECTS) -o kernel.elf
os.iso: kernel.elf
cp kernel.elf iso/boot/kernel.elf
mkisofs -R \
-b boot/grub/stage2_eltorito \
-no-emul-boot \
-boot-load-size 4 \
-A os \
-input-charset utf8 \
-quiet \
-boot-info-table \
-o os.iso \
iso
run: os.iso
bochs -f bochsrc.txt -q
%.o: %.c
$(CC) $(CFLAGS) $< -o $#
%.o: %.s
$(AS) $(ASFLAGS) $< -o $#
clean:
rm -rf *.o kernel.elf os.iso
Here's my linker script:
ENTRY(loader) /* the name of the entry label */
SECTIONS {
. = 0x00100000; /* the code should be loaded at 1 MB */
.text ALIGN (0x1000) : /* align at 4 KB */
{
*(.text) /* all text sections from all files */
}
.rodata ALIGN (0x1000) : /* align at 4 KB */
{
*(.rodata*) /* all read-only data sections from all files */
}
.data ALIGN (0x1000) : /* align at 4 KB */
{
*(.data) /* all data sections from all files */
}
.bss ALIGN (0x1000) : /* align at 4 KB */
{
*(COMMON) /* all COMMON sections from all files */
*(.bss) /* all bss sections from all files */
}
}
Any help would be appreciated.
As it turns out, this was solved by cross-compiling GNU Binutils and GCC together (with the same prefix) on my Mac. I did this according to the instructions here.