Headerfile is not properly included - c

A Header file(stdint.h) is not included. I know a lot of code is following, but I have really no idea.
My Files:
gdt.c
/* We need 8 segments */
#include <stdint.h>
#include "gdt.h"
#define GDT_SIZE 8
uint32_t intr;
gdt_entry gdtable[GDT_SIZE];
include/gdt.h
#ifndef GDT_H
#define GDT_H
#include <stdint.h>
struct gdt_entry{
uint_16t limit;
uint_32t base :24;
uint_32t accessbyte :8;
uint_32t limit2 :4;
uint_32t flags2 :4;
uint_32t base2 :8;
}__attribute__((packed));
#endif
include/stdint.h
#ifndef STDINT_H
#define STDINT_H
typedef unsigned long long uint64_t;
typedef unsigned int uint32_t;
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
typedef signed long long int64_t;
typedef signed int int32_t;
typedef signed short int16_t;
typedef signed char int8_t;
#endif
Makefile:
SRCS = $(shell find -name '*.[cS]')
OBJS = $(addsuffix .o,$(basename $(SRCS)))
CC = gcc
LD = ld
ASFLAGS = -m32
CFLAGS = -m32 -Wall -g -fno-stack-protector -I include
LDFLAGS = -melf_i386 -Tkernel.ld
kernel: $(OBJS)
$(LD) $(LDFLAGS) -o $# $^
%.o: %.c
$(CC) $(CFLAGS) -c -o $# $^
%.o: %.S
$(CC) $(ASFLAGS) -c -o $# $^
clean:
rm $(OBJS)
.PHONY: clean
kernel.ld
/* start should be executed first */
ENTRY(_start)
/*
* thats how the sections should be written in the .elf binary
*/
SECTIONS
{
/*
* the first section has a 1MB Offset for the grub bootloader
*/
. = 0x100000;
/*
* the multiboot header comes first
*/
.text : {
*(multiboot)
*(.text)
}
.data ALIGN(4096) : {
*(.data)
}
.rodata ALIGN(4096) : {
*(.rodata)
}
.bss ALIGN(4096) : {
*(.bss)
}
}
gcc output:
gcc -m32 -c -o start.o start.S
gcc -m32 -Wall -g -fno-stack-protector -I include -c -o gdt.o gdt.c
In file included from gdt.c:3:0:
include/gdt.h:5:2: error: unknown type name ‘uint_16t’
include/gdt.h:6:2: error: unknown type name ‘uint_32t’
include/gdt.h:7:2: error: unknown type name ‘uint_32t’
include/gdt.h:8:2: error: unknown type name ‘uint_32t’
include/gdt.h:9:2: error: unknown type name ‘uint_32t’
include/gdt.h:10:2: error: unknown type name ‘uint_32t’
gdt.c:7:1: error: unknown type name ‘gdt_entry’
make: *** [gdt.o] Error 1

I think you should use uint32_t instead of the non-standard uint_32t. It's at least the third variant I've come across, previously I've also seen u_int32_t.

There was another issue:
gdt_entry gdtable[GDT_SIZE]; should be struct gdt_entry gdtable[GDT_SIZE]

Related

No member named 'si' in 'struct pt_regs'

I am trying to compile the following eBPF code,
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
SEC("kprobe/do_sys_openat2")
int kprobe__do_sys_openat2(struct pt_regs *ctx)
{
char file_name[256];
bpf_probe_read(file_name, sizeof(file_name), PT_REGS_PARM2(ctx));
char fmt[] = "open file %s\n.";
bpf_trace_printk(fmt, sizeof(fmt), &file_name);
return 0;
}
using the following Makefile,
OUTPUT = ./output
LIBBPF = ../libbpf
LIBBPF_SRC = $(abspath $(LIBBPF)/src)
LIBBPF_OBJ = $(abspath $(OUTPUT)/libbpf.a)
CC = gcc
CLANG = clang
ARCH := $(shell uname -m)
# ARCH := $(subst x86_64,amd64,$(ARCH))
GOARCH := $(ARCH)
BPFTOOL = $(shell which bpftool || /bin/false)
BTFFILE = /sys/kernel/btf/vmlinux
DBGVMLINUX = /usr/lib/debug/boot/vmlinux-$(shell uname -r)
GIT = $(shell which git || /bin/false)
VMLINUXH = vmlinux.h
# libbpf
LIBBPF_OBJDIR = $(abspath ./$(OUTPUT)/libbpf)
LIBBPF_DESTDIR = $(abspath ./$(OUTPUT))
CFLAGS = -ggdb -gdwarf -O2 -Wall -fpie -Wno-unused-variable -Wno-unused-function
LDFLAGS =
BPF_CFLAGS_STATIC = "-I$(abspath $(OUTPUT))"
BPF_LDFLAGS_STATIC = "-lelf -lz $(LIBBPF_OBJ)"
CGO_CFLAGS_STATIC = "-I$(abspath $(OUTPUT))"
CGO_LDFLAGS_STATIC = "-lelf -lz $(LIBBPF_OBJ)"
CGO_EXTLDFLAGS_STATIC = '-w -extldflags "-static"'
CGO_CFGLAGS_DYN = "-I. -I/usr/include/"
CGO_LDFLAGS_DYN = "-lelf -lz -lbpf"
CGO_EXTLDFLAGS_DYN = '-w'
## program
.PHONY: $(PROGRAM)
.PHONY: $(PROGRAM).bpf.c
PROGRAM = main
all:
$(MAKE) -C . $(PROGRAM)
# vmlinux header file
.PHONY: vmlinuxh
vmlinuxh: $(VMLINUXH)
$(VMLINUXH): $(OUTPUT)
ifeq ($(wildcard $(BPFTOOL)),)
#echo "ERROR: could not find bpftool"
#exit 1
endif
#if [ -f $(DBGVMLINUX) ]; then \
echo "INFO: found dbg kernel, generating $(VMLINUXH) from $(DBGVMLINUX)"; \
$(BPFTOOL) btf dump file $(DBGVMLINUX) format c > $(VMLINUXH); \
fi
#if [ ! -f $(BTFFILE) ] && [ ! -f $(DBGVMLINUX) ]; then \
echo "ERROR: kernel does not seem to support BTF"; \
exit 1; \
fi
#if [ ! -f $(VMLINUXH) ]; then \
echo "INFO: generating $(VMLINUXH) from $(BTFFILE)"; \
$(BPFTOOL) btf dump file $(BTFFILE) format c > $(VMLINUXH); \
fi
# static libbpf generation for the git submodule
.PHONY: libbpf
libbpf: $(LIBBPF_OBJ)
$(LIBBPF_OBJ): $(LIBBPF_SRC) $(wildcard $(LIBBPF_SRC)/*.[ch]) | $(OUTPUT)/libbpf
CC="$(CC)" CFLAGS="$(CFLAGS)" LD_FLAGS="$(LDFLAGS)" \
$(MAKE) -C $(LIBBPF_SRC) \
BUILD_STATIC_ONLY=1 \
OBJDIR=$(LIBBPF_OBJDIR) \
DESTDIR=$(LIBBPF_DESTDIR) \
INCLUDEDIR= LIBDIR= UAPIDIR= prefix= libdir= install
$(LIBBPF_SRC):
ifeq ($(wildcard $#), )
echo "INFO: updating submodule 'libbpf'"
$(GIT) submodule update --init --recursive
endif
# output dir
$(OUTPUT):
mkdir -p $(OUTPUT)
$(OUTPUT)/libbpf:
mkdir -p $(OUTPUT)/libbpf
## program bpf dependency
$(PROGRAM).bpf.o: $(PROGRAM).bpf.c | vmlinuxh
$(CLANG) $(CFLAGS) -target bpf -D__TARGET_ARCH_x86 -I. -I$(OUTPUT) -c $< -o $#
## GO example
.PHONY: $(PROGRAM)
$(PROGRAM): libbpf | $(PROGRAM).bpf.o
CC=$(CLANG) \
CGO_CFLAGS=$(CGO_CFLAGS_STATIC) \
CGO_LDFLAGS=$(CGO_LDFLAGS_STATIC) \
GOARCH=$(GOARCH) \
go build \
-tags netgo -ldflags $(CGO_EXTLDFLAGS_STATIC) \
-o $(PROGRAM) ./$(PROGRAM).go
## clean
clean:
$(MAKE) -C $(LIBBPF_SRC) clean
rm -rf $(OUTPUT)
rm -rf $(VMLINUXH)
rm -rf $(PROGRAM) $(PROGRAM)-*static $(PROGRAM)-*dynamic
rm -rf $(PROGRAM).bpf.o $(PROGRAM).o
I am getting the error,
error: no member named 'si' in 'struct pt_regs'
bpf_probe_read(file_name, sizeof(file_name), PT_REGS_PARM2(ctx));
^~~~~~~~~~~~~~~~~~
./output/bpf/bpf_tracing.h:273:46: note: expanded from macro 'PT_REGS_PARM2'
#define PT_REGS_PARM2(x) (__PT_REGS_CAST(x)->__PT_PARM2_REG)
~~~~~~~~~~~~~~~~~ ^
./output/bpf/bpf_tracing.h:78:24: note: expanded from macro '__PT_PARM2_REG'
#define __PT_PARM2_REG si
^
I realized this is due to some problem with the definition of the MACRO PT_REGS_PARM2, which is defined as #define PT_REGS_PARM2(x) (__PT_REGS_CAST(x)->__PT_PARM2_REG) in bpf_tracing.h header file, which does some sort of pointer casting to obtain the pt_regs pointer for x, and then access the member given by __PT_PARM2_REG which is a MACRO defined as si. So I guess the error is that there is no such register in my x86 architecture specific struct pt_regs, I am not sure why it uses that register for this macro. Is there any error in the specification of the architecture in Makefile, or is there is some error in the code in bpf_tracing.h? The architecture I am compiling for is x86_64.
So the solution was to replace PT_REGS_PARM2(ctx) by ctx->si directly, since the struct pt_regs is defined inside vmlinux.h itself, and using the macro PT_REGS_PARM2 defaults to using the struct definition inside bpf_tracing.h where the si member is not included for some reason. The struct pt_regs in vmlinux.h is defined as,
struct pt_regs {
long unsigned int r15;
long unsigned int r14;
long unsigned int r13;
long unsigned int r12;
long unsigned int bp;
long unsigned int bx;
long unsigned int r11;
long unsigned int r10;
long unsigned int r9;
long unsigned int r8;
long unsigned int ax;
long unsigned int cx;
long unsigned int dx;
long unsigned int si;
long unsigned int di;
long unsigned int orig_ax;
long unsigned int ip;
long unsigned int cs;
long unsigned int flags;
long unsigned int sp;
long unsigned int ss;
};
So I used pointer casting to get the character pointer to ctx->si, and then read the contents onto file_name as before. The updated ebpf file,
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <string.h>
SEC("kprobe/do_sys_openat2")
int kprobe__do_sys_openat2(struct pt_regs *ctx)
{
char file_name[256];
char *file_name_ptr = (char *)ctx->si;
if (!file_name_ptr)
{
// handle error: invalid memory address
return 0;
}
bpf_probe_read(file_name, sizeof(file_name), file_name_ptr);
char fmt[] = "open file %s\n.";
bpf_trace_printk(fmt, sizeof(fmt), &file_name);
return 0;
}
char _license[] SEC("license") = "GPL";
This works!

Why are these static functions working outside their file?

I defined the next two static functions in a file named Grafico.h.
static inline interface_t * obtener_intf_por_nombre(nodo_t *nodo, char *nombre_if) {
for (int i = 0; i < MAX_INTF_POR_NODO; ++i)
{
if(!nodo->intf[i]) return NULL;
if(strncmp(nodo->intf[i]->nombre_if, nombre_if, TAM_NOMBRE_IF) == 0) {
return nodo->intf[i];
}
}
return NULL;
}
static inline nodo_t * obtener_nodo_por_nombre(grafico_t *topologia, char *nombre_nodo) {
return obtener_elemento(topologia->lista_nodos, nombre_nodo);
}
In my main file I called these functions without remembering they were static, and I didn't get any warning or error from the compiler related to it.
#include <stdio.h>
#include "Net.h"
#include "Grafico.h"
#include "Topologias.h"
#include "CommandParser/libcli.h"
#include "clired.c"
extern grafico_t *const_primera_topo();
grafico_t *topo = NULL;
int main(void) {
inic_cli_red();
topo = const_primera_topo();
sleep(2);
nodo_t *nodo_trans = obtener_nodo_por_nombre(topo, "R0");
interface_t *interface_trans = obtener_intf_por_nombre(nodo_trans, "ethR0/0");
char *mensaje = "Este es un mensaje de prueba\0";
printf("Llegamos hasta aquí señores. Fue un honor.\n");
enviar_paquete(mensaje, strlen(mensaje), interface_trans);
start_shell();
return 0;
}
In case it's useful, here is my makefile.
TARGET = $(BIN_DIR)/sim_tcp_ip
LIBS = -lpthread -L ./CommandParser -lcli -lrt
OBJS = $(OBJ_DIR)/prueba.o \
$(OBJ_DIR)/ListaEnlazadaGenerica.o \
$(OBJ_DIR)/Grafico.o \
$(OBJ_DIR)/Net.o \
$(OBJ_DIR)/Topologias.o \
$(OBJ_DIR)/Com.o \
$(OBJ_DIR)/Utiles.o \
$(OBJ_DIR)/Capa2.o
BIN_DIR = ./bin
OBJ_DIR = ./obj
INC_DIR = ./inc
SRC_DIR = ./src
CFLAGS = -g -lpthread -Wall -I$(INC_DIR)
$(TARGET): $(OBJS) CommandParser/libcli.a
mkdir -p $(BIN_DIR)
gcc $(CFLAGS) $(OBJS) -o $(TARGET) $(LIBS)
$(OBJ_DIR)/%.o : %.c
mkdir -p $(OBJ_DIR)
gcc -c -MD $(CFLAGS) $< -o $#
CommandParser/libcli.a:
(cd CommandParser; make)
-include $(OBJ_DIR)/*.d
.PHONY: clean
clean:
rm -rf $(OBJ_DIR) $(BIN_DIR)
(cd CommandParser; make clean)
all:
make
Is there something wrong with the definition of these static functions?
When you #include a file, it is equivalent to copypasting the contents of that file in place of that line. So the static functions are in the same compilation unit, and hence just as usable as any other static thing you define in the .c file itself.
The problem is that you have declared them in your header file, Graphico.h!
The static keyword just means that if you compile a source C file prog.c into an object file prog.o, then any static functions in prog.c will be hard coded as memory addresses in prog.o. That is to say, whereas a normal function has an entry defined in the symbol table of prog.o, that is used when prog.o is linked with another object file, a static function does not.

Getting errors from crtdefs.h

After a battle trying to include ncurses in my project with makefile, when i try to make .o files it gaves me this errors:
In file included from C:/MinGW/x86_64-w64-mingw32/include/stddef.h:7,
from C:/MinGW/lib/gcc/x86_64-w64-mingw32/8.1.0/include/stddef.h:1,
from C:/MinGW/include/stdint.h:54,
from C:/MinGW/include/ncursesw/curses.h:63,
from src/main.c:1:
C:/MinGW/x86_64-w64-mingw32/include/crtdefs.h:35:18: error: expected ';' before 'typedef'
__MINGW_EXTENSION typedef unsigned __int64 size_t;
^~~~~~~~
;
C:/MinGW/x86_64-w64-mingw32/include/crtdefs.h:45:18: error: expected ';' before 'typedef'
__MINGW_EXTENSION typedef __int64 ssize_t;
^~~~~~~~
;
C:/MinGW/x86_64-w64-mingw32/include/crtdefs.h:62:18: error: expected ';' before 'typedef'
__MINGW_EXTENSION typedef __int64 intptr_t;
^~~~~~~~
;
C:/MinGW/x86_64-w64-mingw32/include/crtdefs.h:75:18: error: expected ';' before 'typedef'
__MINGW_EXTENSION typedef unsigned __int64 uintptr_t;
^~~~~~~~
;
C:/MinGW/x86_64-w64-mingw32/include/crtdefs.h:88:18: error: expected ';' before 'typedef'
__MINGW_EXTENSION typedef __int64 ptrdiff_t;
^~~~~~~~
;
C:/MinGW/x86_64-w64-mingw32/include/crtdefs.h:123:18: error: expected ';' before 'typedef'
__MINGW_EXTENSION typedef __int64 __time64_t;
^~~~~~~~
;
In file included from C:/MinGW/include/stdio.h:94,
from C:/MinGW/include/ncursesw/curses.h:164,
from src/main.c:1:
C:/MinGW/include/sys/types.h:123:21: error: conflicting types for 'ssize_t'
typedef _ssize_t ssize_t;
^~~~~~~
In file included from C:/MinGW/x86_64-w64-mingw32/include/stddef.h:7,
from C:/MinGW/lib/gcc/x86_64-w64-mingw32/8.1.0/include/stddef.h:1,
from C:/MinGW/include/stdint.h:54,
from C:/MinGW/include/ncursesw/curses.h:63,
from src/main.c:1:
C:/MinGW/x86_64-w64-mingw32/include/crtdefs.h:45:35: note: previous declaration of 'ssize_t' was here
__MINGW_EXTENSION typedef __int64 ssize_t;
This is my makefile:
PROJECT=ProjectName
CC=gcc
CFLAGS=-Wall -std=c11
CPPFLAGS = -MMD -MP
CFLAGS = -Wall $(INC) -g3
LIBS = -L"C:/MinGW/lib" -L"C:/MinGW/x86_64-w64-mingw32/lib" -g3
INC = -I"C:/MinGW/include" -I"C:/MinGW/x86_64-w64-mingw32/include" -I"C:/MinGW/lib/gcc/x86_64-w64-mingw32/8.1.0/include"
SRC_DIR:=src
OBJ_DIR:=obj
BIN_DIR:=bin
EXE:=$(BIN_DIR)/$(PROJECT)
SRC:=$(wildcard $(SRC_DIR)/*.c)
OBJ:=$(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
-include $(OBJ:.o=.d)
all: $(EXE)
.PHONY: all clean
$(EXE): $(OBJ) | $(BIN_DIR)
#echo ---------------------------Linking
$(CC) $(OBJ) -o $# $(LIBS)
$(OBJ_DIR)/%.o: $(SRC) | $(OBJ_DIR)
#echo ---------------------------Creating .o files
$(CC) -c $< -o $# $(CFLAGS)
$(OBJ_DIR) $(BIN_DIR):
#echo ---------------------------Creating Directory
mkdir $#
#echo ---------------------------Directory Created
clean:
#echo ---------------------------Clean started
rmdir /Q /S $(OBJ_DIR)
rmdir /Q /S $(BIN_DIR)
#echo ---------------------------Clean finished
I am learning to programming in C and i couldn't found nothing related with this and others errors with ncurses saying that curses.h didn't exist(i tried this both directives ncursesw/curses.h and curses.h). I dont know if OS matter but I'm running in windows. The main code is just a test code for this compilation:
#include <ncursesw/curses.h>
#include <stdlib.h>
int main()
{
int x=10;
initscr();
raw();
printw("%d",x);
getch();
endwin();
return 0;
}
I just reinstalled MinGw Posix and didn't merge the opt folder with include folder, probably I accidentally rewrited crtdefs.h the first time i installed MinGW.

Forcing Orders in Makefile Dependencies

I need some help writing a GNU makefile. I have a C program "main.c", which is dependent on the value of "CONSTANT" defined in the file "constants.h".
"main.c"
#include <stdio.h>
#include "constants.h"
void work(void)
{
int array[CONSTANT];
for (int i = 0; i < CONSTANT; i++) {
printf("%d\n", i);
}
}
int main(int argc, char const* argv[])
{
printf("constant=%d\n", CONSTANT);
work();
return 0;
}
"constant.h"
#ifndef CONSTANTS_H
#define CONSTANTS_H
#define CONSTANT 4
#endif
What I'm trying to do here is to compile the program with different values for "CONSTANT". For example, "out1" is compiled with "CONSTANT=1" and with "make all", I should be able to produce all the variants ("out1", "out2" and "out4").
The problem is that "a.o" required by "main.c" also depends on the value of "CONSTANT". So "a.o" must be compiled after "sed%". However, as far as I understand, there is no way in "make" to force orders in dependencies (I guess this is the whole point of using makefiles).
What is the recommended way to address this situation?
"Makefile"
CC= gcc
CFLAGS = -std=c99 -Wall
CONSTANTS = 1 2 4
targets = $(addprefix out, $(CONSTANTS))
seds = $(addprefix sed, $(CONSTANTS))
.PHONY: $(seds)
$(seds): sed%:
sed -i 's/define CONSTANT [0-9]*/define CONSTANT $*/g' constants.h
$(targets): out%: main.c sed% a.o
$(CC) $(CFLAGS) $< a.o -o $#
a.o: a.c constant.h
$(CC) $(CFLAGS) $< a.o -o $#
.PHONY: all
all : $(targets)
Note that I'm aware that I can rewrite "main.c" so that it takes a parameter from the comman line. In practice, many other files other than "main.c" depend on "CONSTANT", so I want to avoid rewriting all these files. I'm also aware that I can do something like "gcc -DCONSTANT=n main.c", but every file dependent on "CONSTANT" must be recompiled as well.
Related Questions
How to specify Makefile target building order without put any physical dependencies?
Force order of dependencies in a Makefile
I'm ... aware that I can do something like "gcc -DCONSTANT=n main.c",
but every file dependent on "CONSTANT" must be recompiled as well.
This needn't be a hindrance if you have your makefile generate
the correct -DCONSTANT=n and distinct object file in every compilation recipe.
Here's an illustration:
constants.h
#ifndef CONSTANTS_H
#define CONSTANTS_H
#ifndef CONSTANT
#define CONSTANT 4
#endif
#endif
foo.c
#include "constants.h"
int foo = CONSTANT;
main.c
#include <stdio.h>
#include "constants.h"
extern int foo;
int main()
{
printf("%d\n",CONSTANT + foo);
return 0;
}
Makefile
CC := gcc
CFLAGS := -std=c99 -Wall
CONSTANTS = 1 2 4
TARGETS = $(addprefix out, $(CONSTANTS))
SRCS := main.c foo.c
define compile =
$(basename $(1))$(2).o: $(1) constants.h
$$(CC) -c -DCONSTANT=$(2) $$(CFLAGS) $$< -o $$#
endef
.PHONY: all clean
all : $(TARGETS)
$(foreach src,$(SRCS),\
$(foreach const,$(CONSTANTS),$(eval $(call compile,$(src),$(const)))))
out%: main%.o foo%.o
$(CC) $^ -o $#
clean:
rm -f $(TARGETS) *.o
This runs like:
$ make
gcc -c -DCONSTANT=1 -std=c99 -Wall main.c -o main1.o
gcc -c -DCONSTANT=1 -std=c99 -Wall foo.c -o foo1.o
gcc main1.o foo1.o -o out1
gcc -c -DCONSTANT=2 -std=c99 -Wall main.c -o main2.o
gcc -c -DCONSTANT=2 -std=c99 -Wall foo.c -o foo2.o
gcc main2.o foo2.o -o out2
gcc -c -DCONSTANT=4 -std=c99 -Wall main.c -o main4.o
gcc -c -DCONSTANT=4 -std=c99 -Wall foo.c -o foo4.o
gcc main4.o foo4.o -o out4
And the resulting programs run like:
$ for i in 1 2 4; do ./out$i; done
2
4
8

Hexagon compiler having trouble with `typedef struct mystruct *mystruct` [duplicate]

This question already has answers here:
Is it a good idea to typedef pointers?
(15 answers)
Closed 6 years ago.
I have this line in a header file:
typedef struct mystruct *mystruct;
And the corresponding struct definition in a .c file. Pretty standard practices.
I am getting this compilation error:
fatal error: typedef redefinition with different types ('struct mystruct *' vs mystruct')
This is using the Hexagon Tools Compiler (7.2.12) from Hexagon 3.0 SDK. It is officially QuIC LLVM Hexagon Clang version 7.2.12. Building for Snapdragon Flight. This should work as far as I know. It works with Ubuntu clang version 3.5.0-4ubuntu2~trusty2 (based on LLVM 3.5.0) for x86_64-pc-linux-gnu.
What is wrong here? Is this type of typedef a newer feature of C that is not implemented in the compiler, or rather are compiler differences like these common?
Edit: Actually struct is defined in a .c, not .cpp, file. Added the Makefile and make output showing compilation with Ubuntu clang, as well as the top of the header file with the troublesome typedef statment. A test is run at the end, and all 105 tests pass.
Edit2: See Jonathan Leffler's answer for cases where this works vs doesn't work.
ringbuf.h:
#include <stddef.h>
#include <sys/types.h>
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
typedef struct ringbuf_t *ringbuf_t;
Makefile:
CC=clang
CFLAGS=-O0 -g -Wall -Wpointer-arith -ftrapv -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error
# or, for gcc...
#CC=gcc
#CFLAGS=-O0 -g -Wall
LD=$(CC)
LDFLAGS=-g
test: ringbuf-test
./ringbuf-test
coverage: ringbuf-test-gcov
./ringbuf-test-gcov
gcov -o ringbuf-gcov.o ringbuf.c
valgrind: ringbuf-test
valgrind ./ringbuf-test
help:
#echo "Targets:"
#echo
#echo "test - build and run ringbuf unit tests."
#echo "coverage - use gcov to check test coverage of ringbuf.c."
#echo "valgrind - use valgrind to check for memory leaks."
#echo "clean - remove all targets."
#echo "help - this message."
ringbuf-test-gcov: ringbuf-test-gcov.o ringbuf-gcov.o
gcc -o ringbuf-test-gcov --coverage $^
ringbuf-test-gcov.o: ringbuf-test.c ringbuf.h
gcc -c $< -o $#
ringbuf-gcov.o: ringbuf.c ringbuf.h
gcc --coverage -c $< -o $#
ringbuf-test: ringbuf-test.o libringbuf.so
$(LD) -o ringbuf-test $(LDFLAGS) $^ -L$(MY_LIBS_PATH) -lringbuf
ringbuf-test.o: ringbuf-test.c ringbuf.h
$(CC) $(CFLAGS) -c $< -o $#
libringbuf.so: ringbuf.o
$(CC) -shared -o libringbuf.so ringbuf.o
cp ./libringbuf.so $(MY_LIBS_PATH)/
ringbuf.o: ringbuf.c ringbuf.h
$(CC) $(CFLAGS) -fPIC -c $< -o $#
cp ./ringbuf.h $(MY_INCLUDES_PATH)/
clean:
rm -f ringbuf-test ringbuf-test-gcov *.o *.so *.gcov *.gcda *.gcno
.PHONY: clean
make output:
clang -O0 -g -Wall -Wpointer-arith -ftrapv -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -c ringbuf-test.c -o ringbuf-test.o
clang -O0 -g -Wall -Wpointer-arith -ftrapv -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -fPIC -c ringbuf.c -o ringbuf.o
cp ./ringbuf.h /home/eric/Includes/
clang -shared -o libringbuf.so ringbuf.o
cp ./libringbuf.so /home/eric/Libs/
clang -o ringbuf-test -g ringbuf-test.o libringbuf.so -L/home/eric/Libs -lringbuf
./ringbuf-test
Edit3: This actually works fine with just the Hexagon-clang compiler. It is the compilation process of the larger program that this module exists in that is being problematic. I think that it is attempting to compile this code as C++.
Your code would be fine, in C and C++, if you did not try to Use typedef for a pointer type.
The header (hdr.h for instance) could/should contain:
typedef struct mystruct mystruct;
The source (hdr.cpp for instance) could contain:
#include "hdr.h"
struct mystruct
{
const char *a;
int b;
int c;
};
#include <iostream>
int main()
{
mystruct *ap = new mystruct;
ap->a = "collywobbles";
ap->b = 1;
ap->c = 2;
std::cout << "a: " << ap->a << ", b = " << ap->b << ", c = " << ap->c << "\n";
return 0;
}
This will compile in C++, even under stringent warnings. An equivalent C main() using <stdio.h> would work in C.

Resources