diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/README.md b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/README.md new file mode 100644 index 00000000..aa3e5e0d --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/README.md @@ -0,0 +1,15 @@ +# Fixing the Entry Point 1 + +Access the directory `drills/tasks/entry-fix-1/support/`. +We want to track issues with defining the `main()` function. + +Go to the subdirectory `a-c/`. +Run the `make` command, interpret the encountered error, and resolve it by editing the `hello.c` file. + +Go to the subdirectory `b-asm/`. +Run the `make` command, interpret the encountered error, and resolve it by editing the `hello.asm` file. + +**Bonus**: In the subdirectories `c-extra-nolibc/` and `d-extra-libc/`, find solutions that do not modify the source code of `hello.c`. +These solutions instead modify the build system to use a different function, other than `main()`, as the program's entry point. + +If you're having difficulties solving this exercise, go through [this](../../../reading/README.md) reading material. diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/a-c/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/a-c/.gitignore new file mode 100644 index 00000000..e92569d0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/a-c/.gitignore @@ -0,0 +1 @@ +/hello diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/a-c/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/a-c/Makefile new file mode 120000 index 00000000..19ab98b2 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/a-c/Makefile @@ -0,0 +1 @@ +../../support/a-c/Makefile \ No newline at end of file diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/a-c/hello.c b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/a-c/hello.c new file mode 100644 index 00000000..7a4ba956 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/a-c/hello.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +static void hi(void) +{ + puts("Hi!"); +} + +static void bye(void) +{ + puts("Bye!"); +} + +int main(void) +{ + hi(); + bye(); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/b-asm/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/b-asm/.gitignore new file mode 100644 index 00000000..e92569d0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/b-asm/.gitignore @@ -0,0 +1 @@ +/hello diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/b-asm/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/b-asm/Makefile new file mode 120000 index 00000000..072e0b96 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/b-asm/Makefile @@ -0,0 +1 @@ +../../support/b-asm/Makefile \ No newline at end of file diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/b-asm/hello.asm b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/b-asm/hello.asm new file mode 100644 index 00000000..43bf35ca --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/b-asm/hello.asm @@ -0,0 +1,41 @@ +; SPDX-License-Identifier: BSD-3-Clause + +extern puts +extern main + +section .rodata + + hi_str db "Hi!", 0 + bye_str db "Bye!", 0 + +section .text + +hi: + push ebp + mov ebp, esp + + push hi_str + call puts + + leave + ret + +bye: + push ebp + mov ebp, esp + + push bye_str + call puts + + leave + ret + +main: + push ebp + mov ebp, esp + + call hi + call bye + + leave + ret diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/c-extra-nolibc/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/c-extra-nolibc/.gitignore new file mode 100644 index 00000000..e92569d0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/c-extra-nolibc/.gitignore @@ -0,0 +1 @@ +/hello diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/c-extra-nolibc/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/c-extra-nolibc/Makefile new file mode 100644 index 00000000..e58b4d63 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/c-extra-nolibc/Makefile @@ -0,0 +1,25 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -nostdlib -nostdinc -no-pie -m32 +AS = nasm +ASFLAGS = -f elf32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: hello + +hello: hello.o start.o puts.o + $(CC) $(LDFLAGS) -o $@ $^ + +hello.o: hello.c + +start.o: start.asm + $(AS) $(ASFLAGS) -o $@ $< + +puts.o: puts.asm + $(AS) $(ASFLAGS) -o $@ $< + +clean: + -rm -f hello hello.o start.o puts.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/c-extra-nolibc/hello.c b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/c-extra-nolibc/hello.c new file mode 100644 index 00000000..9a5e1355 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/c-extra-nolibc/hello.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +static void hi(void) +{ + puts("Hi!\n"); +} + +static void bye(void) +{ + puts("Bye!\n"); +} + +int my_main(void) +{ + hi(); + bye(); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/c-extra-nolibc/puts.asm b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/c-extra-nolibc/puts.asm new file mode 100644 index 00000000..57a09ded --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/c-extra-nolibc/puts.asm @@ -0,0 +1,51 @@ +; SPDX-License-Identifier: BSD-3-Clause + +section .text + +global puts + +; /usr/include/x86_64-linux-gnu/asm/unistd_32.h +__NR_write equ 4 + +; Argument is message to be printed to standard output. +puts: + push ebp + mov ebp, esp + + ; Call __NR_write(1, message, message_len) (system call). + ; + ; Use x86 Linux system call convention. + ; https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#Making_a_system_call + ; + ; eax stores the system call id. + ; ebx stores the first system call argument: 1 (standard output). + ; ecx stores the second system call argument: message. + ; edc stores the third system call argument: message length. + + ; Store the write system call id in eax. + mov eax, __NR_write + + ; Store standard output file descriptor (1) in ebx. + mov ebx, 1 + + ; Store function argument (message) in ecx. + mov ecx, [ebp + 8] + + ; Compute message length in edx. + ; Find NUL byte address of message using edi. Start from message address (ecx). + ; Then edx <- edi - ecx. + mov edi, ecx + dec edi +again: + inc edi + cmp byte [edi], 0 + jne again + + mov edx, edi + sub edx, ecx + + ; Do system call. + int 0x80 + + leave + ret diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/c-extra-nolibc/start.asm b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/c-extra-nolibc/start.asm new file mode 100644 index 00000000..51a69879 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/c-extra-nolibc/start.asm @@ -0,0 +1,30 @@ +; SPDX-License-Identifier: BSD-3-Clause + +extern my_main + +section .text + +; /usr/include/x86_64-linux-gnu/asm/unistd_32.h +__NR_exit equ 1 + +global _start + +_start: + call my_main + + ; Call __NR_exit(main_return_value) (system call). + ; + ; Use x86 Linux system call convention. + ; https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#Making_a_system_call + ; + ; ebx stores the first system call argument. + ; eax stores the system call id. + + ; eax is main return value. Store it in ebx. + mov ebx, eax + + ; Store the exit system call id in rax. + mov eax, __NR_exit + + ; Do system call. + int 0x80 diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/d-extra-libc/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/d-extra-libc/.gitignore new file mode 100644 index 00000000..e92569d0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/d-extra-libc/.gitignore @@ -0,0 +1 @@ +/hello diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/d-extra-libc/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/d-extra-libc/Makefile new file mode 100644 index 00000000..f88b8414 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/d-extra-libc/Makefile @@ -0,0 +1,22 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 +AS = nasm +ASFLAGS = -f elf32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: hello + +hello: hello.o start.o + ld -static -m elf_i386 -L/usr/lib/gcc/x86_64-linux-gnu/7/32/ -o $@ $^ /usr/lib32/crti.o --start-group -lc -lgcc -lgcc_eh --end-group /usr/lib32/crtn.o + +hello.o: hello.c + +start.o: start.asm + $(AS) $(ASFLAGS) -o $@ $< + +clean: + -rm -f hello hello.o start.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/d-extra-libc/hello.c b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/d-extra-libc/hello.c new file mode 100644 index 00000000..cd6af284 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/d-extra-libc/hello.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +static void hi(void) +{ + puts("Hi!"); +} + +static void bye(void) +{ + puts("Bye!"); +} + +int my_main(void) +{ + hi(); + bye(); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/d-extra-libc/start.asm b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/d-extra-libc/start.asm new file mode 100644 index 00000000..d600983a --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/solution/d-extra-libc/start.asm @@ -0,0 +1,36 @@ +; SPDX-License-Identifier: BSD-3-Clause + +extern __libc_csu_init +extern __libc_csu_fini +extern __libc_start_main +extern my_main + +section .text + +global _start +global _dl_relocate_static_pie + +; Adapted from GNU Libc i386 start.S +; https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/i386/start.S;hb=HEAD +_start: + ; Align stack. + xor ebp, ebp + pop esi + mov ecx, esp + and esp, 0xfffffff0 + + push eax + push esp + push edx + + push __libc_csu_fini + push __libc_csu_init + push ecx + push esi + push my_main + call __libc_start_main + + hlt + +_dl_relocate_static_pie: + repz ret diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/a-c/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/a-c/.gitignore new file mode 100644 index 00000000..e92569d0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/a-c/.gitignore @@ -0,0 +1 @@ +/hello diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/a-c/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/a-c/Makefile new file mode 100644 index 00000000..cbd19a80 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/a-c/Makefile @@ -0,0 +1,17 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: hello + +hello: hello.o + $(CC) $(LDFLAGS) -o $@ $^ + +hello.o: hello.c + +clean: + -rm -f hello hello.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/a-c/hello.c b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/a-c/hello.c new file mode 100644 index 00000000..cd6af284 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/a-c/hello.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +static void hi(void) +{ + puts("Hi!"); +} + +static void bye(void) +{ + puts("Bye!"); +} + +int my_main(void) +{ + hi(); + bye(); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/b-asm/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/b-asm/.gitignore new file mode 100644 index 00000000..e92569d0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/b-asm/.gitignore @@ -0,0 +1 @@ +/hello diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/b-asm/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/b-asm/Makefile new file mode 100644 index 00000000..4985d238 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/b-asm/Makefile @@ -0,0 +1,20 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 +AS = nasm +ASFLAGS = -f elf32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: hello + +hello: hello.o + $(CC) $(LDFLAGS) -o $@ $^ + +hello.o: hello.asm + $(AS) $(ASFLAGS) -o $@ $< + +clean: + -rm -f hello hello.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/b-asm/hello.asm b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/b-asm/hello.asm new file mode 100644 index 00000000..aef141c3 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/b-asm/hello.asm @@ -0,0 +1,40 @@ +; SPDX-License-Identifier: BSD-3-Clause + +extern puts + +section .rodata + + hi_str db "Hi!", 0 + bye_str db "Bye!", 0 + +section .text + +hi: + push ebp + mov ebp, esp + + push hi_str + call puts + + leave + ret + +bye: + push ebp + mov ebp, esp + + push bye_str + call puts + + leave + ret + +main: + push ebp + mov ebp, esp + + call hi + call bye + + leave + ret diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/c-extra-nolibc/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/c-extra-nolibc/.gitignore new file mode 100644 index 00000000..e92569d0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/c-extra-nolibc/.gitignore @@ -0,0 +1 @@ +/hello diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/c-extra-nolibc/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/c-extra-nolibc/Makefile new file mode 100644 index 00000000..e58b4d63 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/c-extra-nolibc/Makefile @@ -0,0 +1,25 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -nostdlib -nostdinc -no-pie -m32 +AS = nasm +ASFLAGS = -f elf32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: hello + +hello: hello.o start.o puts.o + $(CC) $(LDFLAGS) -o $@ $^ + +hello.o: hello.c + +start.o: start.asm + $(AS) $(ASFLAGS) -o $@ $< + +puts.o: puts.asm + $(AS) $(ASFLAGS) -o $@ $< + +clean: + -rm -f hello hello.o start.o puts.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/c-extra-nolibc/hello.c b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/c-extra-nolibc/hello.c new file mode 100644 index 00000000..9a5e1355 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/c-extra-nolibc/hello.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +static void hi(void) +{ + puts("Hi!\n"); +} + +static void bye(void) +{ + puts("Bye!\n"); +} + +int my_main(void) +{ + hi(); + bye(); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/c-extra-nolibc/puts.asm b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/c-extra-nolibc/puts.asm new file mode 100644 index 00000000..57a09ded --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/c-extra-nolibc/puts.asm @@ -0,0 +1,51 @@ +; SPDX-License-Identifier: BSD-3-Clause + +section .text + +global puts + +; /usr/include/x86_64-linux-gnu/asm/unistd_32.h +__NR_write equ 4 + +; Argument is message to be printed to standard output. +puts: + push ebp + mov ebp, esp + + ; Call __NR_write(1, message, message_len) (system call). + ; + ; Use x86 Linux system call convention. + ; https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#Making_a_system_call + ; + ; eax stores the system call id. + ; ebx stores the first system call argument: 1 (standard output). + ; ecx stores the second system call argument: message. + ; edc stores the third system call argument: message length. + + ; Store the write system call id in eax. + mov eax, __NR_write + + ; Store standard output file descriptor (1) in ebx. + mov ebx, 1 + + ; Store function argument (message) in ecx. + mov ecx, [ebp + 8] + + ; Compute message length in edx. + ; Find NUL byte address of message using edi. Start from message address (ecx). + ; Then edx <- edi - ecx. + mov edi, ecx + dec edi +again: + inc edi + cmp byte [edi], 0 + jne again + + mov edx, edi + sub edx, ecx + + ; Do system call. + int 0x80 + + leave + ret diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/c-extra-nolibc/start.asm b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/c-extra-nolibc/start.asm new file mode 100644 index 00000000..51a69879 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/c-extra-nolibc/start.asm @@ -0,0 +1,30 @@ +; SPDX-License-Identifier: BSD-3-Clause + +extern my_main + +section .text + +; /usr/include/x86_64-linux-gnu/asm/unistd_32.h +__NR_exit equ 1 + +global _start + +_start: + call my_main + + ; Call __NR_exit(main_return_value) (system call). + ; + ; Use x86 Linux system call convention. + ; https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#Making_a_system_call + ; + ; ebx stores the first system call argument. + ; eax stores the system call id. + + ; eax is main return value. Store it in ebx. + mov ebx, eax + + ; Store the exit system call id in rax. + mov eax, __NR_exit + + ; Do system call. + int 0x80 diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/d-extra-libc/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/d-extra-libc/.gitignore new file mode 100644 index 00000000..e92569d0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/d-extra-libc/.gitignore @@ -0,0 +1 @@ +/hello diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/d-extra-libc/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/d-extra-libc/Makefile new file mode 100644 index 00000000..f88b8414 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/d-extra-libc/Makefile @@ -0,0 +1,22 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 +AS = nasm +ASFLAGS = -f elf32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: hello + +hello: hello.o start.o + ld -static -m elf_i386 -L/usr/lib/gcc/x86_64-linux-gnu/7/32/ -o $@ $^ /usr/lib32/crti.o --start-group -lc -lgcc -lgcc_eh --end-group /usr/lib32/crtn.o + +hello.o: hello.c + +start.o: start.asm + $(AS) $(ASFLAGS) -o $@ $< + +clean: + -rm -f hello hello.o start.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/d-extra-libc/hello.c b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/d-extra-libc/hello.c new file mode 100644 index 00000000..cd6af284 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/d-extra-libc/hello.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +static void hi(void) +{ + puts("Hi!"); +} + +static void bye(void) +{ + puts("Bye!"); +} + +int my_main(void) +{ + hi(); + bye(); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/d-extra-libc/start.asm b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/d-extra-libc/start.asm new file mode 100644 index 00000000..d600983a --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-1/support/d-extra-libc/start.asm @@ -0,0 +1,36 @@ +; SPDX-License-Identifier: BSD-3-Clause + +extern __libc_csu_init +extern __libc_csu_fini +extern __libc_start_main +extern my_main + +section .text + +global _start +global _dl_relocate_static_pie + +; Adapted from GNU Libc i386 start.S +; https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/i386/start.S;hb=HEAD +_start: + ; Align stack. + xor ebp, ebp + pop esi + mov ecx, esp + and esp, 0xfffffff0 + + push eax + push esp + push edx + + push __libc_csu_fini + push __libc_csu_init + push ecx + push esi + push my_main + call __libc_start_main + + hlt + +_dl_relocate_static_pie: + repz ret diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/README.md b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/README.md new file mode 100644 index 00000000..6f71cad8 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/README.md @@ -0,0 +1,6 @@ +# Fixing the Entry Point + +Access the directory `drills/tasks/entry-fix-2/support/`. +Run the `make` command, interpret the encountered error, and resolve it by editing the `hello.c` file. + +If you're having difficulties solving this exercise, go through [this](../../../reading/README.md) reading material. diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/solution/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/solution/.gitignore new file mode 100644 index 00000000..e92569d0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/solution/.gitignore @@ -0,0 +1 @@ +/hello diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/solution/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/solution/Makefile new file mode 120000 index 00000000..a39be4f2 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/solution/Makefile @@ -0,0 +1 @@ +../support/Makefile \ No newline at end of file diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/solution/hello.c b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/solution/hello.c new file mode 100644 index 00000000..7a4ba956 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/solution/hello.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +static void hi(void) +{ + puts("Hi!"); +} + +static void bye(void) +{ + puts("Bye!"); +} + +int main(void) +{ + hi(); + bye(); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/support/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/support/.gitignore new file mode 100644 index 00000000..e92569d0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/support/.gitignore @@ -0,0 +1 @@ +/hello diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/support/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/support/Makefile new file mode 100644 index 00000000..cbd19a80 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/support/Makefile @@ -0,0 +1,17 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: hello + +hello: hello.o + $(CC) $(LDFLAGS) -o $@ $^ + +hello.o: hello.c + +clean: + -rm -f hello hello.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/support/hello.c b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/support/hello.c new file mode 100644 index 00000000..9a410091 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/entry-fix-2/support/hello.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +static void hi(void) +{ + puts("Hi!"); +} + +static void bye(void) +{ + puts("Bye!"); +} + +static int main(void) +{ + hi(); + bye(); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/README.md b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/README.md new file mode 100644 index 00000000..e6d2659c --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/README.md @@ -0,0 +1,7 @@ +# Fixing Export Issues + +Access the directory `drills/tasks/export-fix/support/`. +Each subdirectory (`a-func/`, `b-var/`, `c-var-2/`) contains a problem related to the export of symbols (functions or variables). +In each subdirectory, run the `make` command, identify the issue, and edit the necessary files to resolve it. + +If you're having difficulties solving this exercise, go through [this](../../../reading/README.md) reading material. diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/Makefile new file mode 120000 index 00000000..9da39e10 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/Makefile @@ -0,0 +1 @@ +../../support/a-func/Makefile \ No newline at end of file diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/hidden.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/hidden.c new file mode 100644 index 00000000..cb83f459 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/hidden.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include "ops.h" + +int hidden_value; + +void init(void) +{ + hidden_value = 0; +} + +void set(int value) +{ + hidden_value = value; +} + +int get(void) +{ + return hidden_value; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/main.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/main.c new file mode 100644 index 00000000..ac72986f --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/main.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + set(10); + printf("get(): %d\n", get()); + + age = 33; + print_age(); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/ops.h b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/ops.h new file mode 100644 index 00000000..22d3d3ac --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/ops.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +void init(void); +void set(int value); +int get(void); + +extern int age; +void print_age(void); + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/plain.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/plain.c new file mode 100644 index 00000000..b620ed57 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/a-func/plain.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int age; + +void print_age(void) +{ + printf("age: %d\n", age); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/Makefile new file mode 120000 index 00000000..32ae761d --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/Makefile @@ -0,0 +1 @@ +../../support/b-var/Makefile \ No newline at end of file diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/hidden.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/hidden.c new file mode 100644 index 00000000..5f8b1ec5 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/hidden.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include "ops.h" + +static int hidden_value; + +void init(void) +{ + hidden_value = 0; +} + +void set(int value) +{ + hidden_value = value; +} + +int get(void) +{ + return hidden_value; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/main.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/main.c new file mode 100644 index 00000000..ac72986f --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/main.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + set(10); + printf("get(): %d\n", get()); + + age = 33; + print_age(); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/ops.h b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/ops.h new file mode 100644 index 00000000..22d3d3ac --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/ops.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +void init(void); +void set(int value); +int get(void); + +extern int age; +void print_age(void); + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/plain.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/plain.c new file mode 100644 index 00000000..b620ed57 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/b-var/plain.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int age; + +void print_age(void) +{ + printf("age: %d\n", age); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/Makefile new file mode 120000 index 00000000..0f2e757a --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/Makefile @@ -0,0 +1 @@ +../../support/c-var-2/Makefile \ No newline at end of file diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/hidden.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/hidden.c new file mode 100644 index 00000000..cb83f459 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/hidden.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include "ops.h" + +int hidden_value; + +void init(void) +{ + hidden_value = 0; +} + +void set(int value) +{ + hidden_value = value; +} + +int get(void) +{ + return hidden_value; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/main.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/main.c new file mode 100644 index 00000000..ac72986f --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/main.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + set(10); + printf("get(): %d\n", get()); + + age = 33; + print_age(); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/ops.h b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/ops.h new file mode 100644 index 00000000..22d3d3ac --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/ops.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +void init(void); +void set(int value); +int get(void); + +extern int age; +void print_age(void); + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/plain.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/plain.c new file mode 100644 index 00000000..b620ed57 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/solution/c-var-2/plain.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int age; + +void print_age(void) +{ + printf("age: %d\n", age); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/Makefile new file mode 100644 index 00000000..5ed84dd5 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o hidden.o plain.o + $(CC) $(LDFLAGS) -o $@ $^ + +main.o: main.c ops.h + +hidden.o: hidden.c + +plain.o: plain.c + +clean: + -rm -f main main.o hidden.o plain.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/hidden.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/hidden.c new file mode 100644 index 00000000..a864c611 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/hidden.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int hidden_value; + +void init(void) +{ + hidden_value = 0; +} + +static void set(int value) +{ + hidden_value = value; +} + +int get(void) +{ + return hidden_value; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/main.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/main.c new file mode 100644 index 00000000..ac72986f --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/main.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + set(10); + printf("get(): %d\n", get()); + + age = 33; + print_age(); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/ops.h b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/ops.h new file mode 100644 index 00000000..22d3d3ac --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/ops.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +void init(void); +void set(int value); +int get(void); + +extern int age; +void print_age(void); + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/plain.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/plain.c new file mode 100644 index 00000000..b620ed57 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/a-func/plain.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int age; + +void print_age(void) +{ + printf("age: %d\n", age); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/Makefile new file mode 100644 index 00000000..5ed84dd5 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o hidden.o plain.o + $(CC) $(LDFLAGS) -o $@ $^ + +main.o: main.c ops.h + +hidden.o: hidden.c + +plain.o: plain.c + +clean: + -rm -f main main.o hidden.o plain.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/hidden.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/hidden.c new file mode 100644 index 00000000..a1e11369 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/hidden.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause + +static int hidden_value; + +void init(void) +{ + hidden_value = 0; +} + +void set(int value) +{ + hidden_value = value; +} + +int get(void) +{ + return hidden_value; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/main.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/main.c new file mode 100644 index 00000000..ac72986f --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/main.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + set(10); + printf("get(): %d\n", get()); + + age = 33; + print_age(); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/ops.h b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/ops.h new file mode 100644 index 00000000..22d3d3ac --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/ops.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +void init(void); +void set(int value); +int get(void); + +extern int age; +void print_age(void); + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/plain.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/plain.c new file mode 100644 index 00000000..ce5252a4 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/b-var/plain.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +static int age; + +void print_age(void) +{ + printf("age: %d\n", age); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/Makefile new file mode 100644 index 00000000..5ed84dd5 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o hidden.o plain.o + $(CC) $(LDFLAGS) -o $@ $^ + +main.o: main.c ops.h + +hidden.o: hidden.c + +plain.o: plain.c + +clean: + -rm -f main main.o hidden.o plain.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/hidden.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/hidden.c new file mode 100644 index 00000000..56b13cc7 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/hidden.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause + +extern int hidden_value; + +void init(void) +{ + hidden_value = 0; +} + +void set(int value) +{ + hidden_value = value; +} + +int get(void) +{ + return hidden_value; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/main.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/main.c new file mode 100644 index 00000000..ac72986f --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/main.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + set(10); + printf("get(): %d\n", get()); + + age = 33; + print_age(); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/ops.h b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/ops.h new file mode 100644 index 00000000..4c92c019 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/ops.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +void init(void); +void set(int value); +int get(void); + +void print_age(void); + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/plain.c b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/plain.c new file mode 100644 index 00000000..ce5252a4 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/export-fix/support/c-var-2/plain.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +static int age; + +void print_age(void) +{ + printf("age: %d\n", age); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/include-fix/README.md b/chapters/hardware-software-interface/linking/drills/tasks/include-fix/README.md new file mode 100644 index 00000000..3adcc22f --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/include-fix/README.md @@ -0,0 +1,10 @@ +# Warning (not an error) + +Access the directory `drills/tasks/include-fix/support/`. +Run the `make` command. +A warning appears, but it is from the preprocessing/compilation process. +Resolve this warning by editing the `hello.c` file. + +**Bonus**: Fix the warning without using the `#include` directive. + +If you're having difficulties solving this exercise, go through [this](../../../reading/README.md) reading material. diff --git a/chapters/hardware-software-interface/linking/drills/tasks/include-fix/solution/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/include-fix/solution/.gitignore new file mode 100644 index 00000000..e92569d0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/include-fix/solution/.gitignore @@ -0,0 +1 @@ +/hello diff --git a/chapters/hardware-software-interface/linking/drills/tasks/include-fix/solution/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/include-fix/solution/Makefile new file mode 120000 index 00000000..a39be4f2 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/include-fix/solution/Makefile @@ -0,0 +1 @@ +../support/Makefile \ No newline at end of file diff --git a/chapters/hardware-software-interface/linking/drills/tasks/include-fix/solution/hello.c b/chapters/hardware-software-interface/linking/drills/tasks/include-fix/solution/hello.c new file mode 100644 index 00000000..7a4ba956 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/include-fix/solution/hello.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +static void hi(void) +{ + puts("Hi!"); +} + +static void bye(void) +{ + puts("Bye!"); +} + +int main(void) +{ + hi(); + bye(); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/include-fix/support/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/include-fix/support/.gitignore new file mode 100644 index 00000000..e92569d0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/include-fix/support/.gitignore @@ -0,0 +1 @@ +/hello diff --git a/chapters/hardware-software-interface/linking/drills/tasks/include-fix/support/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/include-fix/support/Makefile new file mode 100644 index 00000000..cbd19a80 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/include-fix/support/Makefile @@ -0,0 +1,17 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: hello + +hello: hello.o + $(CC) $(LDFLAGS) -o $@ $^ + +hello.o: hello.c + +clean: + -rm -f hello hello.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/include-fix/support/hello.c b/chapters/hardware-software-interface/linking/drills/tasks/include-fix/support/hello.c new file mode 100644 index 00000000..ef112487 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/include-fix/support/hello.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-3-Clause + +static void hi(void) +{ + puts("Hi!"); +} + +static void bye(void) +{ + puts("Bye!"); +} + +int main(void) +{ + hi(); + bye(); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/README.md b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/README.md new file mode 100644 index 00000000..22c03e33 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/README.md @@ -0,0 +1,7 @@ +# Fixing Library Issues + +Access the directory `drills/tasks/lib-fix/support/`. +Run the `make` command, interpret the encountered error, and resolve it by editing the `Makefile`. +Refer to the `Makefile` in the directory `drills/tasks/multiple-link/support/example/c-lib/`. + +If you're having difficulties solving this exercise, go through [this](../../../reading/README.md) reading material. diff --git a/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/Makefile new file mode 100644 index 00000000..6ce73763 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/Makefile @@ -0,0 +1,24 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o libops.a + $(CC) $(LDFLAGS) -o $@ $< -L. -lops + +main.o: main.c ops.h + +libops.a: add.o sub.o + ar rc $@ $^ + +add.o: add.c + +sub.o: sub.c + +clean: + -rm -f main main.o libops.a add.o sub.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/add.c b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/add.c new file mode 100644 index 00000000..e0e2717e --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/add.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int add(int a, int b) +{ + return a+b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/main.c b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/main.c new file mode 100644 index 00000000..77b52aa2 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/main.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + printf("add(10, 3): %d\n", add(10, 3)); + printf("sub(10, 3): %d\n", sub(10, 3)); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/ops.h b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/ops.h new file mode 100644 index 00000000..f1ce5712 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/ops.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +int add(int a, int b); +int sub(int a, int b); + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/sub.c b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/sub.c new file mode 100644 index 00000000..9968ecd4 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/solution/sub.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int sub(int a, int b) +{ + return a-b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/Makefile new file mode 100644 index 00000000..ae0a14ef --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/Makefile @@ -0,0 +1,24 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o libops.a + $(CC) $(LDFLAGS) -o $@ $< -lops + +main.o: main.c ops.h + +libops.a: add.o sub.o + ar rc $@ $^ + +add.o: add.c + +sub.o: sub.c + +clean: + -rm -f main main.o libops.a add.o sub.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/add.c b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/add.c new file mode 100644 index 00000000..e0e2717e --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/add.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int add(int a, int b) +{ + return a+b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/main.c b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/main.c new file mode 100644 index 00000000..77b52aa2 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/main.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + printf("add(10, 3): %d\n", add(10, 3)); + printf("sub(10, 3): %d\n", sub(10, 3)); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/ops.h b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/ops.h new file mode 100644 index 00000000..f1ce5712 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/ops.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +int add(int a, int b); +int sub(int a, int b); + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/sub.c b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/sub.c new file mode 100644 index 00000000..9968ecd4 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/lib-fix/support/sub.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int sub(int a, int b) +{ + return a-b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/README.md b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/README.md new file mode 100644 index 00000000..5467c1a1 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/README.md @@ -0,0 +1,19 @@ +# Linking Multiple Files + +Access the directory `drills/tasks/multiple-link/support/example/`. +We want to follow the linking commands from multiple C source files: `main.c`, `add.c`, `sub.c`. + +As in the previous exercises, there are three subdirectories for three different scenarios: + +* `a-no-header/`: external function declarations are made directly in the C source file (`main.c`) +* `b-header/`: external function declarations are made in a separate header file (`ops.h`) +* `c-lib/`: external function declarations are made in a separate header file, and linking is done using a static library + +In each subdirectory, we use the `make` command to compile the executable file `main`. + +Access the directory `drills/tasks/multiple-link/support/diy/`. +We want to compile and link the source files in each subdirectory, following the model of the previous exercise. + +Copy the `Makefile` files and update them in each subdirectory to obtain the executable file. + +If you're having difficulties solving this exercise, go through [this](../../../reading/README.md) reading material. diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/a-no-header/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/a-no-header/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/a-no-header/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/a-no-header/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/a-no-header/Makefile new file mode 100644 index 00000000..d061297f --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/a-no-header/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o mul.o div.o + $(CC) $(LDFLAGS) -o $@ $^ + +main.o: main.c + +mul.o: mul.c + +div.o: div.c + +clean: + -rm -f main main.o mul.o div.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/a-no-header/div.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/a-no-header/div.c new file mode 100644 index 00000000..e6008ce3 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/a-no-header/div.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int div(int a, int b) +{ + return a / b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/a-no-header/main.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/a-no-header/main.c new file mode 100644 index 00000000..f3f79c0b --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/a-no-header/main.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int mul(int a, int b); +int div(int a, int b); + +int main(void) +{ + printf("mul(10, 5): %d\n", mul(10, 5)); + printf("div(10, 5): %d\n", div(10, 5)); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/a-no-header/mul.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/a-no-header/mul.c new file mode 100644 index 00000000..6bd2ce0c --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/a-no-header/mul.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int mul(int a, int b) +{ + return a * b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/Makefile new file mode 100644 index 00000000..a02b4371 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o mul.o div.o + $(CC) $(LDFLAGS) -o $@ $^ + +main.o: main.c ops.h + +mul.o: mul.c + +div.o: div.c + +clean: + -rm -f main main.o mul.o div.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/div.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/div.c new file mode 100644 index 00000000..e6008ce3 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/div.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int div(int a, int b) +{ + return a / b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/main.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/main.c new file mode 100644 index 00000000..5a550178 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/main.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + printf("mul(10, 5): %d\n", mul(10, 5)); + printf("div(10, 5): %d\n", div(10, 5)); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/mul.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/mul.c new file mode 100644 index 00000000..6bd2ce0c --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/mul.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int mul(int a, int b) +{ + return a * b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/ops.h b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/ops.h new file mode 100644 index 00000000..ae09152c --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/b-header/ops.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +int mul(int a, int b); +int div(int a, int b); + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/.gitignore new file mode 100644 index 00000000..da1bcad5 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/.gitignore @@ -0,0 +1,2 @@ +/main +/libops.a diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/Makefile new file mode 100644 index 00000000..913b8962 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/Makefile @@ -0,0 +1,24 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o libops.a + $(CC) $(LDFLAGS) -o $@ $< -L. -lops + +main.o: main.c ops.h + +libops.a: mul.o div.o + ar rc $@ $^ + +mul.o: mul.c + +div.o: div.c + +clean: + -rm -f main main.o libops.a mul.o div.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/div.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/div.c new file mode 100644 index 00000000..e6008ce3 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/div.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int div(int a, int b) +{ + return a / b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/main.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/main.c new file mode 100644 index 00000000..5a550178 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/main.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + printf("mul(10, 5): %d\n", mul(10, 5)); + printf("div(10, 5): %d\n", div(10, 5)); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/mul.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/mul.c new file mode 100644 index 00000000..6bd2ce0c --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/mul.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int mul(int a, int b) +{ + return a * b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/ops.h b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/ops.h new file mode 100644 index 00000000..ae09152c --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/solution/c-lib/ops.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +int mul(int a, int b); +int div(int a, int b); + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/a-no-header/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/a-no-header/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/a-no-header/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/a-no-header/div.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/a-no-header/div.c new file mode 100644 index 00000000..e6008ce3 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/a-no-header/div.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int div(int a, int b) +{ + return a / b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/a-no-header/main.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/a-no-header/main.c new file mode 100644 index 00000000..f3f79c0b --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/a-no-header/main.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int mul(int a, int b); +int div(int a, int b); + +int main(void) +{ + printf("mul(10, 5): %d\n", mul(10, 5)); + printf("div(10, 5): %d\n", div(10, 5)); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/a-no-header/mul.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/a-no-header/mul.c new file mode 100644 index 00000000..6bd2ce0c --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/a-no-header/mul.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int mul(int a, int b) +{ + return a * b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/b-header/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/b-header/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/b-header/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/b-header/div.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/b-header/div.c new file mode 100644 index 00000000..e6008ce3 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/b-header/div.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int div(int a, int b) +{ + return a / b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/b-header/main.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/b-header/main.c new file mode 100644 index 00000000..5a550178 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/b-header/main.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + printf("mul(10, 5): %d\n", mul(10, 5)); + printf("div(10, 5): %d\n", div(10, 5)); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/b-header/mul.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/b-header/mul.c new file mode 100644 index 00000000..6bd2ce0c --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/b-header/mul.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int mul(int a, int b) +{ + return a * b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/b-header/ops.h b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/b-header/ops.h new file mode 100644 index 00000000..ae09152c --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/b-header/ops.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +int mul(int a, int b); +int div(int a, int b); + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/c-lib/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/c-lib/.gitignore new file mode 100644 index 00000000..da1bcad5 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/c-lib/.gitignore @@ -0,0 +1,2 @@ +/main +/libops.a diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/c-lib/div.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/c-lib/div.c new file mode 100644 index 00000000..e6008ce3 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/c-lib/div.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int div(int a, int b) +{ + return a / b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/c-lib/main.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/c-lib/main.c new file mode 100644 index 00000000..5a550178 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/c-lib/main.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + printf("mul(10, 5): %d\n", mul(10, 5)); + printf("div(10, 5): %d\n", div(10, 5)); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/c-lib/mul.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/c-lib/mul.c new file mode 100644 index 00000000..6bd2ce0c --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/c-lib/mul.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int mul(int a, int b) +{ + return a * b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/c-lib/ops.h b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/c-lib/ops.h new file mode 100644 index 00000000..ae09152c --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/diy/c-lib/ops.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +int mul(int a, int b); +int div(int a, int b); + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/a-no-header/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/a-no-header/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/a-no-header/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/a-no-header/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/a-no-header/Makefile new file mode 100644 index 00000000..61a30e12 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/a-no-header/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o add.o sub.o + $(CC) $(LDFLAGS) -o $@ $^ + +main.o: main.c + +add.o: add.c + +sub.o: sub.c + +clean: + -rm -f main main.o add.o sub.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/a-no-header/add.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/a-no-header/add.c new file mode 100644 index 00000000..36db038f --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/a-no-header/add.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int add(int a, int b) +{ + return a + b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/a-no-header/main.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/a-no-header/main.c new file mode 100644 index 00000000..8fdec81f --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/a-no-header/main.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int add(int a, int b); +int sub(int a, int b); + +int main(void) +{ + printf("add(10, 3): %d\n", add(10, 3)); + printf("sub(10, 3): %d\n", sub(10, 3)); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/a-no-header/sub.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/a-no-header/sub.c new file mode 100644 index 00000000..ecde8e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/a-no-header/sub.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int sub(int a, int b) +{ + return a - b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/Makefile new file mode 100644 index 00000000..8dfe243f --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o add.o sub.o + $(CC) $(LDFLAGS) -o $@ $^ + +main.o: main.c ops.h + +add.o: add.c + +sub.o: sub.c + +clean: + -rm -f main main.o add.o sub.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/add.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/add.c new file mode 100644 index 00000000..36db038f --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/add.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int add(int a, int b) +{ + return a + b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/main.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/main.c new file mode 100644 index 00000000..77b52aa2 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/main.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + printf("add(10, 3): %d\n", add(10, 3)); + printf("sub(10, 3): %d\n", sub(10, 3)); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/ops.h b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/ops.h new file mode 100644 index 00000000..f1ce5712 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/ops.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +int add(int a, int b); +int sub(int a, int b); + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/sub.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/sub.c new file mode 100644 index 00000000..ecde8e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/b-header/sub.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int sub(int a, int b) +{ + return a - b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/.gitignore new file mode 100644 index 00000000..da1bcad5 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/.gitignore @@ -0,0 +1,2 @@ +/main +/libops.a diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/Makefile new file mode 100644 index 00000000..6ce73763 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/Makefile @@ -0,0 +1,24 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o libops.a + $(CC) $(LDFLAGS) -o $@ $< -L. -lops + +main.o: main.c ops.h + +libops.a: add.o sub.o + ar rc $@ $^ + +add.o: add.c + +sub.o: sub.c + +clean: + -rm -f main main.o libops.a add.o sub.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/add.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/add.c new file mode 100644 index 00000000..36db038f --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/add.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int add(int a, int b) +{ + return a + b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/main.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/main.c new file mode 100644 index 00000000..77b52aa2 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/main.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + printf("add(10, 3): %d\n", add(10, 3)); + printf("sub(10, 3): %d\n", sub(10, 3)); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/ops.h b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/ops.h new file mode 100644 index 00000000..f1ce5712 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/ops.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +int add(int a, int b); +int sub(int a, int b); + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/sub.c b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/sub.c new file mode 100644 index 00000000..ecde8e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/multiple-link/support/example/c-lib/sub.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int sub(int a, int b) +{ + return a - b; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/README.md b/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/README.md new file mode 100644 index 00000000..6acbd113 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/README.md @@ -0,0 +1,14 @@ +# Linking an Object File (without Source Code) + +Access the directory `drills/tasks/obj-link-dev/support/`. +The file `shop.o` exposes an interface (functions and variables) that allows displaying messages. +Edit the `main.c` file to properly call the exposed interface and display the messages: + +```bash +price is 21 +quantity is 42 +``` + +Explore the interface and the content of the functions in the `shop.o` file using `nm` and `objdump`. + +If you're having difficulties solving this exercise, go through [this](../../../reading/README.md) reading material. diff --git a/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/solution/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/solution/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/solution/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/solution/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/solution/Makefile new file mode 120000 index 00000000..a39be4f2 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/solution/Makefile @@ -0,0 +1 @@ +../support/Makefile \ No newline at end of file diff --git a/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/solution/main.c b/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/solution/main.c new file mode 100644 index 00000000..a474d2e7 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/solution/main.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/* + * Use 'nm' to find symbols in shop.o + * Then, use 'objdump' to inspect the object + * code of the functions, in order to get + * the prototypes. + */ +extern int set_price(int price); +extern void print_price(void); + +extern int qty; +extern void print_quantity(void); + +int main(void) +{ + set_price(21); + print_price(); + + qty = 42; + print_quantity(); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/support/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/support/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/support/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/support/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/support/Makefile new file mode 100644 index 00000000..96218971 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/support/Makefile @@ -0,0 +1,15 @@ +CFLAGS = -Wall -g + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o shop.o + +main.o: main.c + +clean: + -rm -f main main.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/support/main.c b/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/support/main.c new file mode 100644 index 00000000..0328c1af --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/obj-link-dev/support/main.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int main(void) +{ + /* + * TODO: Make it so you print: + * price is 21 + * quantity is 42 + * without directly calling a printing function. + */ + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/README.md b/chapters/hardware-software-interface/linking/drills/tasks/single-link/README.md new file mode 100644 index 00000000..a37a32c0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/README.md @@ -0,0 +1,34 @@ +# Linking a Single File + +Access the directory `drills/tasks/single-link/support/example/`. +We want to follow the linking commands for a single C source file. +The source file is `hello.c`. + +In the three subdirectories, you will find support files for the following scenarios: + +- `a-dynamic/`: creating a dynamic executable file +- `b-static/`: creating a static executable file +- `c-standalone/`: creating a standalone executable file without the standard C library + +In each subdirectory, we use the `make` command to compile the executable file `hello`. +We use the command `file hello` to check whether the file is compiled dynamically or statically. + +In the `Makefile` files, the linking command uses `gcc`. +An equivalent command that directly uses `ld` is commented out. +To track the direct usage of `ld`, we can comment out the `gcc` command and uncomment the `ld` command. + +In the case of `c-standalone/`, since we are not using the standard C library or C runtime library, we need to replace their functionalities. +The functionalities are replaced in the `start.asm` and `puts.asm` files. +These files implement the `_start` function/symbol and the `puts` function, respectively. +The `_start` function/symbol is, by default, the entry point of an executable program. +The `_start` function is responsible for calling the `main` function and terminating the program. +Because there is no standard library, these two files are written in assembly language and use system calls. + +**Bonus**: Add a command in the `Makefile` in the `c-standalone/` directory that explicitly uses `ld` for linking. + +Access the directory `drills/tasks/single-link/support/diy/`. +We want to compile and link the source files in each subdirectory, following the model of the previous exercise. + +Copy the `Makefile` files and update them in each subdirectory to obtain the executable file. + +If you're having difficulties solving this exercise, go through [this](../../../reading/README.md) reading material. diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/a-dynamic/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/a-dynamic/.gitignore new file mode 100644 index 00000000..04b61914 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/a-dynamic/.gitignore @@ -0,0 +1 @@ +/name diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/a-dynamic/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/a-dynamic/Makefile new file mode 100644 index 00000000..2b196f0a --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/a-dynamic/Makefile @@ -0,0 +1,18 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: name + +name: name.o + $(CC) $(LDFLAGS) -o $@ $^ + #ld -dynamic-linker /lib/ld-linux.so.2 -m elf_i386 -o $@ /usr/lib32/crt1.o /usr/lib32/crti.o $^ -lc /usr/lib32/crtn.o + +name.o: name.c + +clean: + -rm -f name name.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/a-dynamic/name.c b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/a-dynamic/name.c new file mode 100644 index 00000000..b09291fa --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/a-dynamic/name.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int main(void) +{ + puts("Hi, my name is TODO."); + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/b-static/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/b-static/.gitignore new file mode 100644 index 00000000..04b61914 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/b-static/.gitignore @@ -0,0 +1 @@ +/name diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/b-static/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/b-static/Makefile new file mode 100644 index 00000000..e1e86265 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/b-static/Makefile @@ -0,0 +1,18 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -static -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: name + +name: name.o + $(CC) $(LDFLAGS) -o $@ $^ + #ld -static -m elf_i386 -L/usr/lib/gcc/x86_64-linux-gnu/7/32/ -o $@ /usr/lib32/crt1.o /usr/lib32/crti.o $^ --start-group -lc -lgcc -lgcc_eh --end-group /usr/lib32/crtn.o + +name.o: name.c + +clean: + -rm -f name name.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/b-static/name.c b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/b-static/name.c new file mode 100644 index 00000000..b09291fa --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/b-static/name.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int main(void) +{ + puts("Hi, my name is TODO."); + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/c-standalone/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/c-standalone/.gitignore new file mode 100644 index 00000000..04b61914 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/c-standalone/.gitignore @@ -0,0 +1 @@ +/name diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/c-standalone/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/c-standalone/Makefile new file mode 100644 index 00000000..a52306c0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/c-standalone/Makefile @@ -0,0 +1,24 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -nostdinc -nostdlib -no-pie -m32 +AS = nasm +ASFLAGS = -f elf32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: name + +name: name.o start.o puts.o + +name.o: name.c + +start.o: start.asm + $(AS) $(ASFLAGS) -o $@ $< + +puts.o: puts.asm + $(AS) $(ASFLAGS) -o $@ $< + +clean: + -rm -f name name.o start.o puts.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/c-standalone/name.c b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/c-standalone/name.c new file mode 100644 index 00000000..57a203f1 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/c-standalone/name.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int puts(const char *); + +int main(void) +{ + puts("Hi, my name is TODO.\n"); + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/c-standalone/puts.asm b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/c-standalone/puts.asm new file mode 100644 index 00000000..57a09ded --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/c-standalone/puts.asm @@ -0,0 +1,51 @@ +; SPDX-License-Identifier: BSD-3-Clause + +section .text + +global puts + +; /usr/include/x86_64-linux-gnu/asm/unistd_32.h +__NR_write equ 4 + +; Argument is message to be printed to standard output. +puts: + push ebp + mov ebp, esp + + ; Call __NR_write(1, message, message_len) (system call). + ; + ; Use x86 Linux system call convention. + ; https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#Making_a_system_call + ; + ; eax stores the system call id. + ; ebx stores the first system call argument: 1 (standard output). + ; ecx stores the second system call argument: message. + ; edc stores the third system call argument: message length. + + ; Store the write system call id in eax. + mov eax, __NR_write + + ; Store standard output file descriptor (1) in ebx. + mov ebx, 1 + + ; Store function argument (message) in ecx. + mov ecx, [ebp + 8] + + ; Compute message length in edx. + ; Find NUL byte address of message using edi. Start from message address (ecx). + ; Then edx <- edi - ecx. + mov edi, ecx + dec edi +again: + inc edi + cmp byte [edi], 0 + jne again + + mov edx, edi + sub edx, ecx + + ; Do system call. + int 0x80 + + leave + ret diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/c-standalone/start.asm b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/c-standalone/start.asm new file mode 100644 index 00000000..c384e42b --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/solution/c-standalone/start.asm @@ -0,0 +1,30 @@ +; SPDX-License-Identifier: BSD-3-Clause + +extern main + +section .text + +; /usr/include/x86_64-linux-gnu/asm/unistd_32.h +__NR_exit equ 1 + +global _start + +_start: + call main + + ; Call __NR_exit(main_return_value) (system call). + ; + ; Use x86 Linux system call convention. + ; https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#Making_a_system_call + ; + ; ebx stores the first system call argument. + ; eax stores the system call id. + + ; eax is main return value. Store it in ebx. + mov ebx, eax + + ; Store the exit system call id in rax. + mov eax, __NR_exit + + ; Do system call. + int 0x80 diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/a-dynamic/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/a-dynamic/.gitignore new file mode 100644 index 00000000..04b61914 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/a-dynamic/.gitignore @@ -0,0 +1 @@ +/name diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/a-dynamic/name.c b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/a-dynamic/name.c new file mode 100644 index 00000000..b09291fa --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/a-dynamic/name.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int main(void) +{ + puts("Hi, my name is TODO."); + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/b-static/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/b-static/.gitignore new file mode 100644 index 00000000..04b61914 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/b-static/.gitignore @@ -0,0 +1 @@ +/name diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/b-static/name.c b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/b-static/name.c new file mode 100644 index 00000000..b09291fa --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/b-static/name.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int main(void) +{ + puts("Hi, my name is TODO."); + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/c-standalone/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/c-standalone/.gitignore new file mode 100644 index 00000000..04b61914 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/c-standalone/.gitignore @@ -0,0 +1 @@ +/name diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/c-standalone/name.c b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/c-standalone/name.c new file mode 100644 index 00000000..57a203f1 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/c-standalone/name.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int puts(const char *); + +int main(void) +{ + puts("Hi, my name is TODO.\n"); + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/c-standalone/puts.asm b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/c-standalone/puts.asm new file mode 100644 index 00000000..57a09ded --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/c-standalone/puts.asm @@ -0,0 +1,51 @@ +; SPDX-License-Identifier: BSD-3-Clause + +section .text + +global puts + +; /usr/include/x86_64-linux-gnu/asm/unistd_32.h +__NR_write equ 4 + +; Argument is message to be printed to standard output. +puts: + push ebp + mov ebp, esp + + ; Call __NR_write(1, message, message_len) (system call). + ; + ; Use x86 Linux system call convention. + ; https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#Making_a_system_call + ; + ; eax stores the system call id. + ; ebx stores the first system call argument: 1 (standard output). + ; ecx stores the second system call argument: message. + ; edc stores the third system call argument: message length. + + ; Store the write system call id in eax. + mov eax, __NR_write + + ; Store standard output file descriptor (1) in ebx. + mov ebx, 1 + + ; Store function argument (message) in ecx. + mov ecx, [ebp + 8] + + ; Compute message length in edx. + ; Find NUL byte address of message using edi. Start from message address (ecx). + ; Then edx <- edi - ecx. + mov edi, ecx + dec edi +again: + inc edi + cmp byte [edi], 0 + jne again + + mov edx, edi + sub edx, ecx + + ; Do system call. + int 0x80 + + leave + ret diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/c-standalone/start.asm b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/c-standalone/start.asm new file mode 100644 index 00000000..c384e42b --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/diy/c-standalone/start.asm @@ -0,0 +1,30 @@ +; SPDX-License-Identifier: BSD-3-Clause + +extern main + +section .text + +; /usr/include/x86_64-linux-gnu/asm/unistd_32.h +__NR_exit equ 1 + +global _start + +_start: + call main + + ; Call __NR_exit(main_return_value) (system call). + ; + ; Use x86 Linux system call convention. + ; https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#Making_a_system_call + ; + ; ebx stores the first system call argument. + ; eax stores the system call id. + + ; eax is main return value. Store it in ebx. + mov ebx, eax + + ; Store the exit system call id in rax. + mov eax, __NR_exit + + ; Do system call. + int 0x80 diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/a-dynamic/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/a-dynamic/.gitignore new file mode 100644 index 00000000..e92569d0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/a-dynamic/.gitignore @@ -0,0 +1 @@ +/hello diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/a-dynamic/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/a-dynamic/Makefile new file mode 100644 index 00000000..3ea76660 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/a-dynamic/Makefile @@ -0,0 +1,18 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: hello + +hello: hello.o + $(CC) $(LDFLAGS) -o $@ $^ + #ld -dynamic-linker /lib/ld-linux.so.2 -m elf_i386 -o $@ /usr/lib32/crt1.o /usr/lib32/crti.o $^ -lc /usr/lib32/crtn.o + +hello.o: hello.c + +clean: + -rm -f hello hello.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/a-dynamic/hello.c b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/a-dynamic/hello.c new file mode 100644 index 00000000..772630f3 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/a-dynamic/hello.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int main(void) +{ + puts("Hello, World!"); + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/b-static/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/b-static/.gitignore new file mode 100644 index 00000000..e92569d0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/b-static/.gitignore @@ -0,0 +1 @@ +/hello diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/b-static/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/b-static/Makefile new file mode 100644 index 00000000..0ddd2ba7 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/b-static/Makefile @@ -0,0 +1,18 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -static -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: hello + +hello: hello.o + $(CC) $(LDFLAGS) -o $@ $^ + #ld -static -m elf_i386 -L/usr/lib/gcc/x86_64-linux-gnu/7/32/ -o $@ /usr/lib32/crt1.o /usr/lib32/crti.o $^ --start-group -lc -lgcc -lgcc_eh --end-group /usr/lib32/crtn.o + +hello.o: hello.c + +clean: + -rm -f hello hello.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/b-static/hello.c b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/b-static/hello.c new file mode 100644 index 00000000..772630f3 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/b-static/hello.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int main(void) +{ + puts("Hello, World!"); + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/c-standalone/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/c-standalone/.gitignore new file mode 100644 index 00000000..e92569d0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/c-standalone/.gitignore @@ -0,0 +1 @@ +/hello diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/c-standalone/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/c-standalone/Makefile new file mode 100644 index 00000000..4bdeb57d --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/c-standalone/Makefile @@ -0,0 +1,24 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -nostdinc -nostdlib -no-pie -m32 +AS = nasm +ASFLAGS = -f elf32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: hello + +hello: hello.o start.o puts.o + +hello.o: hello.c + +start.o: start.asm + $(AS) $(ASFLAGS) -o $@ $< + +puts.o: puts.asm + $(AS) $(ASFLAGS) -o $@ $< + +clean: + -rm -f hello hello.o start.o puts.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/c-standalone/hello.c b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/c-standalone/hello.c new file mode 100644 index 00000000..8925010a --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/c-standalone/hello.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int puts(const char *); + +int main(void) +{ + puts("Hello, World!\n"); + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/c-standalone/puts.asm b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/c-standalone/puts.asm new file mode 100644 index 00000000..57a09ded --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/c-standalone/puts.asm @@ -0,0 +1,51 @@ +; SPDX-License-Identifier: BSD-3-Clause + +section .text + +global puts + +; /usr/include/x86_64-linux-gnu/asm/unistd_32.h +__NR_write equ 4 + +; Argument is message to be printed to standard output. +puts: + push ebp + mov ebp, esp + + ; Call __NR_write(1, message, message_len) (system call). + ; + ; Use x86 Linux system call convention. + ; https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#Making_a_system_call + ; + ; eax stores the system call id. + ; ebx stores the first system call argument: 1 (standard output). + ; ecx stores the second system call argument: message. + ; edc stores the third system call argument: message length. + + ; Store the write system call id in eax. + mov eax, __NR_write + + ; Store standard output file descriptor (1) in ebx. + mov ebx, 1 + + ; Store function argument (message) in ecx. + mov ecx, [ebp + 8] + + ; Compute message length in edx. + ; Find NUL byte address of message using edi. Start from message address (ecx). + ; Then edx <- edi - ecx. + mov edi, ecx + dec edi +again: + inc edi + cmp byte [edi], 0 + jne again + + mov edx, edi + sub edx, ecx + + ; Do system call. + int 0x80 + + leave + ret diff --git a/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/c-standalone/start.asm b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/c-standalone/start.asm new file mode 100644 index 00000000..c384e42b --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/single-link/support/example/c-standalone/start.asm @@ -0,0 +1,30 @@ +; SPDX-License-Identifier: BSD-3-Clause + +extern main + +section .text + +; /usr/include/x86_64-linux-gnu/asm/unistd_32.h +__NR_exit equ 1 + +global _start + +_start: + call main + + ; Call __NR_exit(main_return_value) (system call). + ; + ; Use x86 Linux system call convention. + ; https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#Making_a_system_call + ; + ; ebx stores the first system call argument. + ; eax stores the system call id. + + ; eax is main return value. Store it in ebx. + mov ebx, eax + + ; Store the exit system call id in rax. + mov eax, __NR_exit + + ; Do system call. + int 0x80 diff --git a/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/README.md b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/README.md new file mode 100644 index 00000000..8ec82d4e --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/README.md @@ -0,0 +1,6 @@ +# Using Symbols (Variables and Functions) + +Access the directory `drills/tasks/10-var-func-fix/support/`. +Run the `make` command, interpret the encountered error, and resolve it by editing the source files. + +If you're having difficulties solving this exercise, go through [this](../../../reading/README.md) reading material. diff --git a/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/solution/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/solution/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/solution/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/solution/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/solution/Makefile new file mode 120000 index 00000000..a39be4f2 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/solution/Makefile @@ -0,0 +1 @@ +../support/Makefile \ No newline at end of file diff --git a/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/solution/main.c b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/solution/main.c new file mode 100644 index 00000000..2b6db291 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/solution/main.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "state.h" + +int main(void) +{ + size_t i; + + init_shopping(); + for (i = 0; i < sizeof(shopping_list) / sizeof(shopping_list[0]); i++) + printf("%s\n", shopping_list[i]); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/solution/state.c b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/solution/state.c new file mode 100644 index 00000000..f03442d2 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/solution/state.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause + +const char *shopping_list[3]; + +void init_shopping(void) +{ + shopping_list[0] = "cheese"; + shopping_list[1] = "wine"; + shopping_list[2] = "dessert"; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/solution/state.h b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/solution/state.h new file mode 100644 index 00000000..7b1b089d --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/solution/state.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef STATE_H_ +#define STATE_H_ 1 + +void init_shopping(void); +extern const char *shopping_list[3]; + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/support/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/support/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/support/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/support/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/support/Makefile new file mode 100644 index 00000000..e6c47716 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/support/Makefile @@ -0,0 +1,19 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o state.o + $(CC) $(LDFLAGS) -o $@ $^ + +main.o: main.c state.h + +state.o: state.c + +clean: + -rm -f main main.o state.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/support/main.c b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/support/main.c new file mode 100644 index 00000000..2b6db291 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/support/main.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "state.h" + +int main(void) +{ + size_t i; + + init_shopping(); + for (i = 0; i < sizeof(shopping_list) / sizeof(shopping_list[0]); i++) + printf("%s\n", shopping_list[i]); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/support/state.c b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/support/state.c new file mode 100644 index 00000000..73b9002c --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/support/state.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause + +const char *init_shopping[3]; + +void shopping_list(void) +{ + init_shopping[0] = "cheese"; + init_shopping[1] = "wine"; + init_shopping[2] = "dessert"; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/support/state.h b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/support/state.h new file mode 100644 index 00000000..7b1b089d --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/var-func-fix/support/state.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef STATE_H_ +#define STATE_H_ 1 + +void init_shopping(void); +extern const char *shopping_list[3]; + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/README.md b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/README.md new file mode 100644 index 00000000..8b67d1b2 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/README.md @@ -0,0 +1,19 @@ +# Using Variables + +Access the directory `drills/tasks/vars-obs/support/`. +We want to track the use of global variables, both exported and non-exported. + +In the `hidden.c` file, we have the static (non-exported) variable `hidden_value`. +This variable is modified and accessed using non-exported functions: `init()`, `get()`, `set()`. + +In the `plain.c` file, we have the exported variable `age`. +This variable can be modified and accessed directly. + +These variables are used directly (`age`) or indirectly (`hidden_value`) in the `main.c` file. +To use them, the functions and variables are declared in the `ops.h` file. +A function is declared by specifying the header. +A variable is declared by prefixing it with `extern`. + +Modify `main.c` such that `hidden_value` is set to 10 and `age` is set to 33. + +If you're having difficulties solving this exercise, go through [this](../../../reading/README.md) reading material. diff --git a/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/Makefile new file mode 120000 index 00000000..a39be4f2 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/Makefile @@ -0,0 +1 @@ +../support/Makefile \ No newline at end of file diff --git a/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/hidden.c b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/hidden.c new file mode 100644 index 00000000..a1e11369 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/hidden.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause + +static int hidden_value; + +void init(void) +{ + hidden_value = 0; +} + +void set(int value) +{ + hidden_value = value; +} + +int get(void) +{ + return hidden_value; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/main.c b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/main.c new file mode 100644 index 00000000..3d775e22 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/main.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +// Function used to validate the result. +extern void check_result(void); + +int main(void) +{ + set(10); + age = 33; + + check_result(); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/ops.h b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/ops.h new file mode 100644 index 00000000..22d3d3ac --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/ops.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +void init(void); +void set(int value); +int get(void); + +extern int age; +void print_age(void); + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/plain.c b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/plain.c new file mode 100644 index 00000000..b620ed57 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/solution/plain.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int age; + +void print_age(void) +{ + printf("age: %d\n", age); +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/.gitignore b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/Makefile b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/Makefile new file mode 100644 index 00000000..dbca39f0 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -fno-PIC -m32 -g +LDFLAGS = -no-pie -m32 + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o hidden.o plain.o checker.o + $(CC) $(LDFLAGS) -o $@ $^ + +main.o: main.c ops.h + +hidden.o: hidden.c + +plain.o: plain.c + +clean: + -rm -f main main.o hidden.o plain.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/hidden.c b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/hidden.c new file mode 100644 index 00000000..a1e11369 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/hidden.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause + +static int hidden_value; + +void init(void) +{ + hidden_value = 0; +} + +void set(int value) +{ + hidden_value = value; +} + +int get(void) +{ + return hidden_value; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/main.c b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/main.c new file mode 100644 index 00000000..6ae481b4 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/main.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +// Function used to validate the result. +extern void check_result(void); + +int main(void) +{ + check_result(); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/ops.h b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/ops.h new file mode 100644 index 00000000..22d3d3ac --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/ops.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +void init(void); +void set(int value); +int get(void); + +extern int age; +void print_age(void); + +#endif diff --git a/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/plain.c b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/plain.c new file mode 100644 index 00000000..b620ed57 --- /dev/null +++ b/chapters/hardware-software-interface/linking/drills/tasks/vars-obs/support/plain.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include + +int age; + +void print_age(void) +{ + printf("age: %d\n", age); +} diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/README.md b/chapters/hardware-software-interface/linking/guides/cpp-obs/README.md new file mode 100644 index 00000000..90ea740f --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/README.md @@ -0,0 +1,28 @@ +# Linking C and C++ + +Access the directory `drills/tasks/cpp-obs/support/`. +We want to observe how linking is performed with mixed sources: C and C++. + +In the `bad/` subdirectory, we have two directories, `c-calls-cpp/` and `cpp-calls-c/`, where we combine C and C++ sources. +In both cases, using `make` displays errors. +This occurs because C++ symbols are *mangled*. + +If we use the `nm` command on object modules obtained from C source code, we get: + +```console +$ nm add.o +0000000000000000 T _Z3addii + +$ nm sub.o +0000000000000000 T _Z3subii +``` + +The symbol names are not `add` and `sub`, but rather `_Z3addii` and `_Z3subii`. +C++ symbol names are *mangled* and define the function signature. +This allows for functions with the same name but different signatures. +Details about *name mangling* can be found [here](https://en.wikipedia.org/wiki/Name_mangling). + +To resolve this, symbols defined in C and imported into C++, or vice versa, must be prefixed with the directive `extern "C"`. +This way, the C++ compiler will use simple names for the imported/exported symbols, allowing them to be used together with C modules. +This is implemented in the `good/` subdirectory. +Details about the `extern "C"` directive can be found [here](https://stackoverflow.com/a/1041880/4804196). diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/.gitignore b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/Makefile b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/Makefile new file mode 100644 index 00000000..63092931 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/Makefile @@ -0,0 +1,22 @@ +CFLAGS = -Wall -g +CXXFLAGS = -Wall -g +LDFLAGS = -lstdc++ + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o add.o sub.o + $(CC) $(LDFLAGS) -o $@ $^ + +main.o: main.c ops.h + +add.o: add.cpp + +sub.o: sub.cpp + +clean: + -rm -f main main.o add.o sub.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/add.cpp b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/add.cpp new file mode 100644 index 00000000..36db038f --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/add.cpp @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int add(int a, int b) +{ + return a + b; +} diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/main.c b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/main.c new file mode 100644 index 00000000..77b52aa2 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/main.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + printf("add(10, 3): %d\n", add(10, 3)); + printf("sub(10, 3): %d\n", sub(10, 3)); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/ops.h b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/ops.h new file mode 100644 index 00000000..f1ce5712 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/ops.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +int add(int a, int b); +int sub(int a, int b); + +#endif diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/sub.cpp b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/sub.cpp new file mode 100644 index 00000000..ecde8e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/c-calls-cpp/sub.cpp @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int sub(int a, int b) +{ + return a - b; +} diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/.gitignore b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/Makefile b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/Makefile new file mode 100644 index 00000000..faa510b3 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -Wall -g +CXXFLAGS = -Wall -g + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o add.o sub.o + $(CXX) $(LDFLAGS) -o $@ $^ + +main.o: main.cpp ops.h + +add.o: add.c + +sub.o: sub.c + +clean: + -rm -f main main.o add.o sub.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/add.c b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/add.c new file mode 100644 index 00000000..36db038f --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/add.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int add(int a, int b) +{ + return a + b; +} diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/main.cpp b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/main.cpp new file mode 100644 index 00000000..1c17429d --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/main.cpp @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + std::cout << "add(10, 3): " << add(10, 3) << std::endl; + std::cout << "sub(10, 3): " << sub(10, 3) << std::endl; + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/ops.h b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/ops.h new file mode 100644 index 00000000..f1ce5712 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/ops.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +int add(int a, int b); +int sub(int a, int b); + +#endif diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/sub.c b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/sub.c new file mode 100644 index 00000000..ecde8e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/bad/cpp-calls-c/sub.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int sub(int a, int b) +{ + return a - b; +} diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/.gitignore b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/Makefile b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/Makefile new file mode 100644 index 00000000..63092931 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/Makefile @@ -0,0 +1,22 @@ +CFLAGS = -Wall -g +CXXFLAGS = -Wall -g +LDFLAGS = -lstdc++ + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o add.o sub.o + $(CC) $(LDFLAGS) -o $@ $^ + +main.o: main.c ops.h + +add.o: add.cpp + +sub.o: sub.cpp + +clean: + -rm -f main main.o add.o sub.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/add.cpp b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/add.cpp new file mode 100644 index 00000000..442f6261 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/add.cpp @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include "ops.h" + +int add(int a, int b) +{ + return a + b; +} diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/main.c b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/main.c new file mode 100644 index 00000000..77b52aa2 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/main.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + printf("add(10, 3): %d\n", add(10, 3)); + printf("sub(10, 3): %d\n", sub(10, 3)); + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/ops.h b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/ops.h new file mode 100644 index 00000000..491ddcb9 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/ops.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +int add(int a, int b); +int sub(int a, int b); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/sub.cpp b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/sub.cpp new file mode 100644 index 00000000..7f8243b7 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/c-calls-cpp/sub.cpp @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include "ops.h" + +int sub(int a, int b) +{ + return a - b; +} diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/.gitignore b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/.gitignore @@ -0,0 +1 @@ +/main diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/Makefile b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/Makefile new file mode 100644 index 00000000..faa510b3 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/Makefile @@ -0,0 +1,21 @@ +CFLAGS = -Wall -g +CXXFLAGS = -Wall -g + +.DEFAULT_GOAL: all + +.PHONY: all clean + +all: main + +main: main.o add.o sub.o + $(CXX) $(LDFLAGS) -o $@ $^ + +main.o: main.cpp ops.h + +add.o: add.c + +sub.o: sub.c + +clean: + -rm -f main main.o add.o sub.o + -rm -f *~ diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/add.c b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/add.c new file mode 100644 index 00000000..36db038f --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/add.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int add(int a, int b) +{ + return a + b; +} diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/main.cpp b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/main.cpp new file mode 100644 index 00000000..1c17429d --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/main.cpp @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include "ops.h" + +int main(void) +{ + std::cout << "add(10, 3): " << add(10, 3) << std::endl; + std::cout << "sub(10, 3): " << sub(10, 3) << std::endl; + + return 0; +} diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/ops.h b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/ops.h new file mode 100644 index 00000000..491ddcb9 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/ops.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef OPS_H_ +#define OPS_H_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +int add(int a, int b); +int sub(int a, int b); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/sub.c b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/sub.c new file mode 100644 index 00000000..ecde8e00 --- /dev/null +++ b/chapters/hardware-software-interface/linking/guides/cpp-obs/support/good/cpp-calls-c/sub.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause + +int sub(int a, int b) +{ + return a - b; +} diff --git a/chapters/hardware-software-interface/linking/reading/README.md b/chapters/hardware-software-interface/linking/reading/README.md new file mode 100644 index 00000000..de09951c --- /dev/null +++ b/chapters/hardware-software-interface/linking/reading/README.md @@ -0,0 +1,225 @@ +# Linking + +Linking is the final phase of the building process. +Linking combines multiple object files into an executable file. + +To obtain an executable file from object files, the linker performs the following actions: + +1. Symbol resolution: locating the undefined symbols of one object file in other object files. +1. Section merging: merging sections of the same type from different object files into a single section in the executable file. +1. Address binding: after merging, the effective address symbols within the executable file can be established. +1. Symbol relocation: once the symbol addresses are set, the instructions and data referring to those addresses in the executable must be updated. +1. Entry point establishment: specifying the address of the first instruction to be executed. + +## Linker Invocation + +The linker is generally invoked by the compilation utility (`gcc`, `clang`, `cl`). +Thus, invoking the linker is transparent to the user. +In specific cases, such as creating a kernel image or images for embedded systems, the user will invoke the linker directly. + +If we have a source C file `app.c`, we will use the compiler to obtain the object file `app.o`: + +```console +gcc -c -o app.o app.c +``` + +Then, to obtain the executable file `app` from the object file `app.o`, we use the `gcc` utility again: + +```console +gcc -o app app.o +``` + +In the background, `gcc` will invoke the linker and build the executable `app`. +The linker will also link against the standard C library (libc). + +The linking process will work only if the file `app.c` has the `main()` function defined, which is the main function of the program. +Linked files must have a single `main()` function in order to produce an executable. + +If we have multiple C source files, we invoke the compiler for each file and then the linker: + +```console +gcc -c -o helpers.o helpers.c +gcc -c -o app.o app.c +gcc -o app app.o helpers.o +``` + +The last command is the linking command, which links the object files `app.o` and `helpers.o` into the executable file `app`. + +In the case of C++ source files, we will use the `g++` command: + +```console +g++ -c -o helpers.o helpers.cpp +g++ -c -o app.o app.cpp +g++ -o app app.o helpers.o +``` + +We can also use the `gcc` command for linking, specifying linking with the standard C++ library (libc++): + +```console +gcc -o app app.o helpers.o -lstdc++ +``` + +The Linux linking utility, `ld`, is invoked transparently by `gcc` or `g++`. +To see how the linker is invoked, we use the `-v` option of the `gcc` utility, with the following output: + +```console +/usr/lib/gcc/x86_64-linux-gnu/7/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/7/liblto_plugin.so +-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper -plugin-opt=-fresolution=/tmp/ccwnf5NM.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_i386 --hash-style=gnu +--as-needed -dynamic-linker /lib/ld-linux.so.2 -z relro -o hello +/usr/lib/gcc/x86_64-linux-gnu/7/../../../i386-linux-gnu/crt1.o +/usr/lib/gcc/x86_64-linux-gnu/7/../../../i386-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/7/32/crtbegin.o +-L/usr/lib/gcc/x86_64-linux-gnu/7/32 -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../i386-linux-gnu +-L/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib32 -L/lib/i386-linux-gnu -L/lib/../lib32 -L/usr/lib/i386-linux-gnu +-L/usr/lib/../lib32 -L/usr/lib/gcc/x86_64-linux-gnu/7 -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../i386-linux-gnu +-L/usr/lib/gcc/x86_64-linux-gnu/7/../../.. -L/lib/i386-linux-gnu -L/usr/lib/i386-linux-gnu hello.o -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/7/32/crtend.o /usr/lib/gcc/x86_64-linux-gnu/7/../../../i386-linux-gnu/crtn.o +COLLECT_GCC_OPTIONS='-no-pie' '-m32' '-v' '-o' 'hello' '-mtune=generic' '-march=i686' +``` + +The `collect2` utility is, in fact, a wrapper around the `ld` utility. +The result of running the command is complex. A "manual" invocation of the `ld` command would look like this: + +```console +ld -dynamic-linker /lib/ld-linux.so.2 -m elf_i386 -o app /usr/lib32/crt1.o /usr/lib32/crti.o app.o helpers.o -lc /usr/lib32/crtn.o +``` + +The arguments of the above command have the following meanings: + +- `-dynamic-linker /lib/ld-linux.so.2`: specifies the dynamic loader/linker used for loading the dynamic executable +- `-m elf_i386`: links files for the x86 architecture (32-bit, i386) +- `/usr/lib32/crt1.o`, `/usr/lib32/crti.o`, `/usr/lib32/crtn.o`: represent the C runtime library (`crt` - *C runtime*) that provides the necessary support for loading the executable +- `-lc`: links against standard C library (libc) + +## File Inspection + +To track the linking process, we use static analysis utilities such as `nm`, `objdump`, and `readelf`. + +We use the `nm` utility to display symbols from an object file or an executable file: + +```console +$ nm hello.o +00000000 T main + U puts + +$ nm hello +0804a01c B __bss_start +0804a01c b completed.7283 +0804a014 D __data_start +0804a014 W data_start +08048370 t deregister_tm_clones +08048350 T _dl_relocate_static_pie +080483f0 t __do_global_dtors_aux +08049f10 t __do_global_dtors_aux_fini_array_entry +0804a018 D __dso_handle +08049f14 d _DYNAMIC +0804a01c D _edata +0804a020 B _end +080484c4 T _fini +080484d8 R _fp_hw +08048420 t frame_dummy +08049f0c t __frame_dummy_init_array_entry +0804861c r __FRAME_END__ +0804a000 d _GLOBAL_OFFSET_TABLE_ + w __gmon_start__ +080484f0 r __GNU_EH_FRAME_HDR +080482a8 T _init +08049f10 t __init_array_end +08049f0c t __init_array_start +080484dc R _IO_stdin_used +080484c0 T __libc_csu_fini +08048460 T __libc_csu_init + U __libc_start_main@@GLIBC_2.0 +08048426 T main + U puts@@GLIBC_2.0 +080483b0 t register_tm_clones +08048310 T _start +0804a01c D __TMC_END__ +08048360 T __x86.get_pc_thunk.bx +``` + +The `nm` command displays three columns: + +- the symbol's address +- the section and type where the symbol is located +- the symbol's name + +A symbol is the name of a global variable or function. +It is used by the linker to make connections between different object modules. +Symbols are not necessary for executables, which is why executables can be stripped. + +The symbol's address is actually the offset within a section for object files and is the effective address for executables. + +The second column specifies the section and type of the symbol. +If it is uppercase, then the symbol is exported and can be used by another module. +If it is lowercase, then the symbol is not exported and is local to the object module, making it unusable in other modules. +Thus: + +- `d`: the symbol is in the initialized data area (`.data`), unexported +- `D`: the symbol is in the initialized data area (`.data`), exported +- `t`: the symbol is in the code area (`.text`), unexported +- `T`: the symbol is in the code area (`.text`), exported +- `r`: the symbol is in the read-only data area (`.rodata`), unexported +- `R`: the symbol is in the read-only data area (`.rodata`), exported +- `b`: the symbol is in the uninitialized data area (`.bss`), unexported +- `B`: the symbol is in the uninitialized data area (`.bss`), exported +- `U`: the symbol is undefined (it is used in the current module but defined in another module) + +More information can be found in the manual page for the `nm` utility. + +Using the `objdump` command, we can disassemble the code of object files and executables. +This way, we can see the assembly code and how the modules operate. + +The `readelf` command is used to inspect object or executable files. +With the `readelf` command, we can view the headers of files. +An important piece of information in the header of executable files is the entry point, the address of the first instruction executed: + +```console +$ readelf -h hello +ELF Header: + Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 + Class: ELF32 + Data: 2's complement, little endian + Version: 1 (current) + OS/ABI: UNIX - System V + ABI Version: 0 + Type: EXEC (Executable file) + Machine: Intel 80386 + Version: 0x1 + Entry point address: 0x8048310 + Start of program headers: 52 (bytes into file) + Start of section headers: 8076 (bytes into file) + Flags: 0x0 + Size of this header: 52 (bytes) + Size of program headers: 32 (bytes) + Number of program headers: 9 + Size of section headers: 40 (bytes) + Number of section headers: 35 + Section header string table index: 34 +``` + +Using the `readelf` command, we can see the sections of an executable/object file: + +```console +$ readelf -S hello +There are 35 section headers, starting at offset 0x1f8c: +Section Headers: + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1 + [ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4 + [ 3] .note.gnu.build-i NOTE 08048188 000188 000024 00 A 0 0 4 +[...] +``` + +Also, with the `readelf` command, we can list (dump) the contents of a specific section: + +```console +$ readelf -x .rodata hello + +Hex dump of section '.rodata': + 0x080484d8 03000000 01000200 48656c6c 6f2c2057 ........Hello, W + 0x080484e8 6f726c64 2100 orld!. +``` diff --git a/config.yaml b/config.yaml index 9300ecec..47fca53c 100644 --- a/config.yaml +++ b/config.yaml @@ -261,6 +261,26 @@ docusaurus: - Overflow in C/: overflow-in-c/ - Overwrite Return Address/: overwrite-ret-addr/ - Overflow for Binary File/: overflow-for-binary/ + - Lab 12 - Linking: + path: chapters/hardware-software-interface/linking/ + subsections: + - Reading/: reading/ + - Drills: + path: drills/ + subsections: + - Tasks: + path: tasks/ + subsections: + - Single File Linking/: single-link/ + - Multiple File Linking/: multiple-link/ + - Entry Point Fixing 1/: entry-fix-1/ + - Entry Point Fixing 2/: entry-fix-2/ + - Warning Resolution/: include-fix/ + - Export Resolution/: export-fix/ + - Linking with Symbols/: var-func-fix/ + - Library Issues Resolution/: lib-fix/ + - Linking an Object File/: obj-link-dev/ + # static_assets: # - template-chapter-template-topic: /build/make_assets/chapters/template-chapter/template-topic/slides/_site config_meta: