object file missing function symbol - c

I am currently writing a short test app.
The compilation gives me these errors :
CC main.c
Building ../bin/pmono
./main.o:(.data+0x18): undefined reference to `busy'
./main.o:(.data+0x58): undefined reference to `busy'
./main.o:(.data+0x98): undefined reference to `busy'
./main.o:(.data+0xd8): undefined reference to `busy'
./main.o:(.data+0x118): undefined reference to `busy'
./main.o:(.data+0x158): more undefined references to `busy' follow
collect2: ld a retourné 1 code d'état d'exécution
I will try to narrow the code down to the specific parts.
Here is a structure I use which contain the desired reference :
/*
* Chained list of blocks from a frame of the cyclic executive
*/
typedef struct block {
long c; /* Worst case execution time */
long d; /* Deadline */
long p; /* Period */
void (*action) (long); /* Action performed by this frame */
struct block * next;
} *Frame;
The function pointer is placeholder for a generic function not written yet, declared as such in the same .h file :
/*
* Load the CPU for a determined time expressed in nanosecond
*/
void busy(long t);
The function is currently hollow in the c file :
void busy(long t) {
}
Finally, here is a sample default structure I use in my tests :
struct block D = {8,20,20,busy,0};
struct block C = {2,20,20,busy,&D};
struct block B = {3,10,10,busy,&C};
struct block A = {1,10,10,busy,&B};
Frame sequence0 = &A;
All of these parts are contained in a common source file shared between numerous implementations of periodic tasks. The compilation of the object file seems fine.
When I try to compile a given implementation, I first include the .h file, compile the .o file, then try to link the whole thing, using makefile. Here is one makefile to give you an idea :
BIN = ../bin/pmono
CC = gcc
SUBDIR = .
SRC = $(foreach dir, $(SUBDIR), $(wildcard $(dir)/*.c))
OBJ = $(SRC:.c=.o) $(wildcard ../common/*.o)
INCLUDES =
WARNINGS =
OPTIMISATION =
DEBUG =
XENO_CONFIG = /usr/xenomai/bin/xeno-config
XENO_POSIX_CFLAGS = $(shell $(XENO_CONFIG) --skin=posix --cflags)
XENO_POSIX_LDFLAGS = $(shell $(XENO_CONFIG) --skin=posix --ldflags)
CFLAGS = $(INCLUDES) $(XENO_POSIX_CFLAGS) $(WARNINGS) $(OPTIMISATION)
LDFLAGS = -lm $(XENO_POSIX_LDFLAGS) $(DEBUG)
all:.depend $(BIN)
%.o:%.c
#echo "CC $<"
#$(CC) -c $(CFLAGS) $< -o $#
$(BIN): $(OBJ)
#echo "Building ${BIN}"
#$(CC) $(OBJ) -o $# $(LDFLAGS)
clean:
rm -f $(OBJ)
distclean: clean
rm -f $(BIN)
rm -f ./.depend
.depend: $(SRC)
#echo "Génération des dépendances"
#$(CC) $(CFLAGS) -MM $(SRC) > .depend
-include .depend
So, I'm a beginner in this, and this is my understanding : the symbol of the busy function is missing in the main.o, while it exists in the cyclic_executive.o file. I don't understand how this is possible, as I include the cyclic_executive.h file, thus giving the proper declaration and prototype.
I think I'm doing it wrong, but I'm short on idea.
Also, I really dislike how I declare my "default" sequence. I know there is a proper way to do it, but I can't recall it... Does someone has a name to help search for it ?
Thanks.

You are not linking the file with the busy() function call.
Try this from the command line:
gcc main.c cyclic_executive.c
If it works, or at least doesn't give errors on the busy() function, that will confirm the issue. Then try
make all
This should print all the commands as they are executed. If you are still in the dark, try
make -d
That will give you a ton of diagnostics about what make is actually doing.

Related

Can't run simple printf on cortex a55

I'm trying to get started with the RK3568 controller (cortex a55)
I have a project and a makefile
I managed to output the character using registers and flashing the LED.
But if I try to output a string using printf, the program just freezes without any signs of life.
I was looking for a solution to the problem, and the main solution is to implement the _write function(int file, char *ptr, int len), which the standard printf function should use. But it doesn't help.
I tried to connect another Printf function from github and it works. I don't understand what the reason is.
I tried to call other functions from the standard library, for example strlen and it has the same behavior as printf
int _write(int file, char *ptr, int len)
{
__io_putchar('w');
int DataIdx;
for (DataIdx = 0; DataIdx < len; DataIdx++)
{
__io_putchar( *ptr++ );
}
return len;
}
I am using the AArch64 bare-metal target compiler (aarch64-none-elf)
I tried using another AArch32 bare-metal target compiler (arm-none-eabi), but there are even more problems with it. He can't even build the project and throws assembler errors.
Error: selected processor does not support requested special purpose register -- `msr tpidr_el 1,xzr'
Error: ARM register expected -- `ldr x1,=_start'
and many more similar
my makefile, maybe its help
PWD := $(shell pwd)
PRJ_BUILD := $(PWD)/build
CC := aarch64-none-elf-gcc
LD := aarch64-none-elf-ld
OBJCOPY := aarch64-none-elf-objcopy
OBJDUMP := aarch64-none-elf-objdump
SRC := src/entry_point.S
SRC += src/cache.S
SRC += src/main.c
SRC += src/stub.c
SRC := $(addprefix $(PWD)/,$(SRC))
INCLUDES := .
INCLUDES += src
INCLUDES := $(addprefix -I$(PWD)/,$(INCLUDES))
CFLAGS := -c -g
#CFLAGS += -march=armv8.2-a -mcpu=cortex-a55
CFLAGS += -mcpu=cortex-a55
#-mcpu=cortex-a55 -mfloat-abi=hard
define get_library_path
$(shell dirname $(shell $(CC) $(CFLAGS) -print-file-name=$(1)))
endef
LDFLAGS += -L $(call get_library_path,libc.a)
LDFLAGS += -L $(call get_library_path,libgcc.a)
LDFLAGS += -T $(PWD)/link.lds -lgcc -lc
all: app.elf
app.elf:
$(info $(PWD))
$(info SRC:[$(SRC)])
$(info INCLUDES:[$(INCLUDES)])
cd $(PRJ_BUILD) && $(CC) $(CFLAGS) $(INCLUDES) $(SRC)
cd $(PRJ_BUILD) && \
$(LD) -o app.elf $(PRJ_BUILD)/*.o \
$(LDFLAGS) -Map app.map
cd $(PRJ_BUILD) && $(OBJCOPY) -O binary app.elf app.bin
cd $(PRJ_BUILD) && $(OBJDUMP) app.elf -dS > app.lst
clean:
cd $(PRJ_BUILD) && rm -f *.*
I would be glad to at least some advice
In the end I was able to solve this problem
I tried to do the following
I implemented the _sbrk function (get from this)
I tried to highlight heap and stack
I implemented the _write function (but did not touch _write_r [!])
I provided the implementation of the memcmp, memset, memmove, memcpy functions
In reality, item No. has the greatest impact on work.4. If you remove everything except point 4, then the code works and I can output "Hello world"!
Let me remind you that I use aarch64-none-elf-gcc
item 4 I took from here https://embeddedartistry.com/blog/2017/03/22/memset-memcpy-memcmp-and-memmove/

**Undefined reference** error while linking two libraries referring to one-another

I am getting undefined reference error while trying to compile main that refers to two libraries. I have two files lib1/func1.c and lib2/func2.c in separate folders. Those files contain two functions print1() and print2(), function print1() is calling print2().
I am compiling those separately into two libraries libfunc1.a and libfunc2.a.
But when I am trying to compile main which is calling print1(), I get the following error:
/usr/bin/ld: /home/sv/ztest2/lib1/libfunc1.a(func1.o): in function print1:
/home/sv/ztest2/lib1/func1.c:7: undefined reference to print2
collect2: error: ld returned 1 exit status
make: *** [Makefile:21: DP] Error 1
Here is the code and Makefiles:
Makefile:
TARGET = DP
HOME = /home/slav/FORECAST/ztest2
INCDIRS = -I./ \
-I$(HOME)/lib1 \
-I$(HOME)/lib2
LIBDIRS = -L$(HOME)/lib1 \
-L$(HOME)/lib2
SRCFILES = DP.c
OBJFILES = DP.o
CFLAGS = -g -O3 $(INCDIRS)
all: $(TARGET)
$(TARGET): $(OBJFILES)
cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc2 -lfunc1
clean:
-rm *.o $(TARGET)
DP.c:
#include "func1.h"
int main()
{
print1();
return 0;
}
func1.h:
void print1();
func1.c:
#include <stdio.h>
void print1()
{
printf("print1 is called!\n");
print2();
}
func2.h:
extern void print2();
func2.c:
#include <stdio.h>
void print2()
{
printf("print2 is called!\n");
}
Libraries must be listed in the order their symbols are needed.
The command cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc2 -lfunc1 tells the linker to first use the func2 library to resolve any pending references in the executable it is building and then to use the func1 library.
Since the linker processes func2 first, and, at the time it does so, there is no pending reference to print2, the linker does not include the module with print2 in the executable.
Later, when the linker is processing func1, it includes the module with print1 in the executable because main uses it. That module print1 uses print2, so including that module adds a new reference to print2. Then, when the linker is done processing func1, it has an unresolved reference. The linker does not go back to func2 to check it again.
Since the func1 library depends on func2, change the link command to cc $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LIBDIRS) -lfunc1 -lfunc2.
(If the func2 library also depends on func1, that is a bad design and should be reconsidered. If it is not changed, asking the linker to reconsider the libraries multiple times, as with -lfunc1 -lfunc2 -lfunc1, might fix the immediate problem, but others can arise.)

multiple definition of `function' error occurring on the same line as "first defined here"

error log
paging.c: In function ‘setup_paging_structures’:
paging.c:7: warning: implicit declaration of function ‘printf’
rm -f bootimg
gcc -nostdlib -static boot.o paging.o x86_desc.o i8259.o kernel.o lib.o paging.o tests.o -Ttext=0x400000 -o bootimg
paging.o: In function `setup_paging_structures':
/workdirmain/work/mp3_group_31/student-distrib/paging.c:4: multiple definition of `setup_paging_structures'
paging.o:/workdirmain/work/mp3_group_31/student-distrib/paging.c:4: first defined here
paging.o: In function `initialize_paging':
/workdirmain/work/mp3_group_31/student-distrib/paging.c:13: multiple definition of `initialize_paging'
paging.o:/workdirmain/work/mp3_group_31/student-distrib/paging.c:13: first defined here
collect2: ld returned 1 exit status
make: *** [bootimg] Error 1
Here's what my paging.h file looks like:
#ifndef _PAGING_H
#define _PAGING_H
#include "types.h"
#define TOTAL_ENTRIES 1024
extern void setup_paging_structures();
extern void initialize_paging();
#endif
Paging.c below:
#include "paging.h" //include header files
void setup_paging_structures(){
int i;
for (i = 0; i < TOTAL_ENTRIES; i++){
printf("weird");
}
return;
}
void initialize_paging(){
setup_paging_structures();
return;
}
Note, I have not called the functions yet.
The command I'm using is "sudo make" (Makefile was given to me. I'm pretty sure I'm not supposed to modify it):
# Makefile for OS project
# To build, first `make dep`, them `make`. Everything should be automatic.
# Will compile all *.c and *.S files in the current directory.
# Flags to use when compiling, preprocessing, assembling, and linking
CFLAGS+=-Wall -fno-builtin -fno-stack-protector -nostdlib
ASFLAGS+=
LDFLAGS+=-nostdlib -static
CC=gcc
#If you have any .h files in another directory, add -I<dir> to this line
CPPFLAGS+=-nostdinc -g
# This generates the list of source files
SRC=$(wildcard *.S) $(wildcard *.c) $(wildcard */*.S) $(wildcard */*.c)
# This generates the list of .o files. The order matters, boot.o must be first
OBJS=boot.o
OBJS+=$(filter-out boot.o,$(patsubst %.S,%.o,$(filter %.S,$(SRC))))
OBJS+=$(patsubst %.c,%.o,$(filter %.c,$(SRC)))
bootimg: Makefile $(OBJS)
rm -f bootimg
$(CC) $(LDFLAGS) $(OBJS) -Ttext=0x400000 -o bootimg
sudo ./debug.sh
dep: Makefile.dep
Makefile.dep: $(SRC)
$(CC) -MM $(CPPFLAGS) $(SRC) > $#
.PHONY: clean
clean:
rm -f *.o */*.o Makefile.dep
ifneq ($(MAKECMDGOALS),dep)
ifneq ($(MAKECMDGOALS),clean)
include Makefile.dep
endif
endif
edit: I added updates to my post including the actual directories, the entire error log, and the contents of the Makefile I am using. This is also for a class that I'm currently taking, hence some of the things that were automatically given to me.

Undefined symbols while linking OSMalloc.h using clang on OS X

Hello and thank you for your assistance.
I'm attempting to create a simple 'hello world' using only low-level OS X kernel calls to allocate memory and write out to stdout. Why? I'm finishing up chapter 8 of 2nd Edition K&R which is focused on writing standard file library from scratch. It is, of course, totally out of date but the concept of the chapter remains. Anyway, I cannot seem to figure out how to properly link to get everything to work out and are thus earning myself lots of nice undefined symbol errors.
I have parsed through many other questions causing the same error, but have not found any that address how to link in the kernel library I'm attempting to use. The crazy long path in the third #include was needed to just get the thing to compile even prior to the link errors.
The Code:
#include <fcntl.h>
#include <unistd.h> // equivalent to (K&R) #include "syscalls.h"
#include </Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/libkern/OSMalloc.h> // for low-level memory allocation
#define MINSTDIOTAG "com.apple.minstdio" // Used by OSMalloc from <libkern/OSMalloc.h>
#define PAGE_SIZE_64K (64 * 1024) // Page size to allocate
int main(void) {
char *base = NULL; // Memory buffer
char *ptr = base; // Location in buffer
// Create tag
OSMallocTag mytag = OSMalloc_Tagalloc(MINSTDIOTAG, OSMT_DEFAULT);
// Attempt to allocate PAGE_SIZE_64K of memory
if ((base = (char *)OSMalloc(PAGE_SIZE_64K, mytag)) == NULL)
return 1;
ptr = base;
// Stuff the buffer with stuff
*ptr++ = 'f';
*ptr++ = 'o';
*ptr++ = 'o';
*ptr++ = '\n';
*ptr = '\0';
// Write it out to stdout
(void)write(STDOUT_FILENO, base, (size_t)(ptr - base));
// Free allocated memory
OSFree(base, PAGE_SIZE_64K, mytag);
// Get out of Dodge City, Kansas
return 0;
}
Makefile:
BIN = ../../bin
ODIR = obj
CC = cc
CFLAGS = -std=c99 -Wall -g -I.
_OBJ = minstdio3.o
_BIN = minstdio3
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
.PHONY: all clean
all: $(_BIN)
clean:
rm -rv $(ODIR) $(_BIN)
minstdio3: $(ODIR)/minstdio3.o
$(CC) $(CFLAGS) $^ -o $#
cp -v $# $(BIN)/$#
$(ODIR)/%.o: %.c $(DEPS)
mkdir -pv $(ODIR)
$(CC) $(CFLAGS) -c -o $# $<
Errors Received:
Todds-MBP-2:cbasics todddecker$ make
mkdir -pv obj
cc -std=c99 -Wall -g -I. -c -o obj/minstdio3.o minstdio3.c
cc -std=c99 -Wall -g -I. obj/minstdio3.o -o minstdio3
Undefined symbols for architecture x86_64:
"_OSFree", referenced from:
_main in minstdio3.o
"_OSMalloc", referenced from:
_main in minstdio3.o
"_OSMalloc_Tagalloc", referenced from:
_main in minstdio3.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [minstdio3] Error 1
-- EDITS --
"Why are you not using the sbrk system call if you want low-level? This would match your use of write and shouldn't give any linking issues." (from CRD)
Using 'sbrk' (and it's cousin 'brk') was the original path I was headed down; however, the man page for 'sbrk' states, "The brk and sbrk functions are historical curiosities left over from earlier days before the advent of virtual memory management." This statement put me on a path toward trying to discover its replacement. 'malloc' is, of course, the correct and normal utility for memory allocation. However, K&R Chapter 8 is all about writing your own from base OS system calls. So, the base call I was able to find for OS X Darwin is 'OSMalloc' which I'm trying to use.
OSMalloc is only available for writing the kernel itself (kernel extensions, device drivers). User programs have to use sbrk.

call c function from a .c file with a main function

I have two .c files that both have mains. One of the files has a function that I would like to use in the other main. Is it possible to reference this other function without copying and pasting it into the other .c file?
No you don't need to copy and paste, suppose you have this
program-one.c
First program.
#include "common.h" /* This should be implemented */
int main(void)
{
do_program_one_stuff();
common_function();
return 0;
}
program-two.c
Second program.
#include "common.h" /* This should be implemented */
int main(void)
{
do_program_two_stuff();
common_function();
return 0;
}
You need a third .c file and a .h file, like this
common.c
Common Functions Implementation.
void common_function()
{
/* Do it here */
}
common.h
Common Functions Header.
void common_function();
You now can compile a single binary for each program consisting of two files, the program specific .c file and common.c.
The right way to do it is to have a Makefile and generate object code first, and then link the object files togeather, thus compiling each file only once.
Makefile
This is a GNU make Makefile using gcc as the compiler.
CC = gcc
CFLAGS = -Wall -Wextra -Werror -g3 -O0 # enable debug symbols and warnings
LDFLAGS = # linker flags here ...
OBJ = common.o program-one.o program-two.o
all:
$(CC) $(LDFLAGS) common.o program-one.o -o program-one
$(CC) $(LDFLAGS) common.o program-two.o -o program-two
%.o: %.c
$(CC) $(CFLAGS) -c $<
clean:
#rm -fv *.o program-one program-two
EDIT: in response to your comment I would suggest the following
#define main ignore /* Or whatever name you want */
#include "the-student-implementation.c"
#undef main
int main(void)
{
/* This would be your `main()' */
return 0;
}
The best solution is what iharob suggested, but if for some reason that isn't possible, you could surround the main() in the file containing the common function with #ifdef USE_MAIN, then only define the USE_MAIN identifier in the command to build that project. When you build the other project that doesn't have USE_MAIN defined, the preprocessor will cause the second main() to be skipped, so the compiler won't be confused.
But unless this is really needed, I highly recommend splitting this into three files: main1.c, main2.c, and common.c/common.h

Resources