summaryrefslogtreecommitdiff
path: root/md/notes/undefined_c/titles.md
diff options
context:
space:
mode:
authorFreeArtMan <dos21h@gmail.com>2022-08-26 10:03:34 +0100
committerFreeArtMan <dos21h@gmail.com>2022-08-26 10:03:34 +0100
commit51e6cef5d338c8ea74572f44c92dab9c0ac13dda (patch)
tree7af9b5dfca63a20b9ed5dbb009f220d31376a25b /md/notes/undefined_c/titles.md
parentaff2574a12174fc58a1bd528a6a9e8c5c4b88903 (diff)
downloadmd-content-51e6cef5d338c8ea74572f44c92dab9c0ac13dda.tar.gz
md-content-51e6cef5d338c8ea74572f44c92dab9c0ac13dda.zip
Renamed undefined c
Diffstat (limited to 'md/notes/undefined_c/titles.md')
-rw-r--r--md/notes/undefined_c/titles.md1749
1 files changed, 0 insertions, 1749 deletions
diff --git a/md/notes/undefined_c/titles.md b/md/notes/undefined_c/titles.md
deleted file mode 100644
index 731d42c..0000000
--- a/md/notes/undefined_c/titles.md
+++ /dev/null
@@ -1,1749 +0,0 @@
-title:Undefined C
-keywords:c,linux,asm
-
-# Undefined C
-
-There is possible to run piece of code inside online c compiler like https://www.onlinegdb.com/online_c_compiler
-Or run locally. With base check is done with gcc compiler. There are many small tricks around running C code
-in practice that aren't covered in any generic tutorials, so here is list of topics that may arise while
-coding real C code outside of tutorials. For each case there is just small example, each of those could
-take whole chapter on its own.
-
-## Compile
-
-
-__hello_world.c__
-```c
-int main() {
- printf("Hello world\n");
-}
-```
-
-```bash
-gcc hello_world.c -o hello_world
-gcc -m32 hello_world.c -o hello_world_32 #for 32bit target
-```
-
-## Syntax
-
-### Variables
-
-Standard list of available types
-
-#### Check type size
-
-All types have size that are declared in bytes. Some of the types are machine dependents.
-like int/long, if there is needed machine independent types then there are int32_t/uint32_t/int64_t/uint64_t
-
-Each architecture 8bit/16bit/32bit/64bit will have different size for those types
-
-Use __sizeof()__
-
-Running on x86 machine
-```c
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdio.h>
-int main() {
- printf("Sizeof int %lu\n",sizeof(int));
- printf("Sizeof int32_t %lu\n",sizeof(int32_t));
- printf("Sizeof int64_t %lu\n",sizeof(int64_t));
- printf("Sizeof long %lu\n",sizeof(long));
- printf("Sizeof long long %lu\n",sizeof(long long));
-}
-```
-
-Most safest/portable way is to use [u]int[8/16/32/64]_t types.
-
-Defined macros'es to get type max and min values are
-
-https://en.cppreference.com/w/c/types/limits
-
-```c
-#include <limits.h>
-int main() {
- printf("INT_MIN %d\n",INT_MIN);
- printf("INT_MAX %d\n", INT_MAX);
- printf("LONG_MIN %ld\n",LONG_MIN);
-}
-```
-
-Example from AVR __stdint.h__
-https://github.com/avrdudes/avr-libc/blob/main/include/stdint.h
-Example from Libc
-https://sourceware.org/git/?p=glibc.git;a=blob;f=stdlib/stdint.h
-
-
-
-#### How to shoot the leg
-
-When code suppose to run on 32bit and 64bit platform the size of type may vary.
-Need to take in account this case.
-
-
-
-
-
-### Functions
-
-Function syntax, there is nothing interesting on functions
-
-```
-<RETURN_TYPE> <NAME>(<TYPE> <NAME>,..) {
- <EXPR>
-}
-```
-
-Write simple function
-
-```c
-int fun1() {
- return -1;
-}
-```
-
-Function can have multiple return statements.
-Here is example whne function have 3 return values.
-```c
-int fun2(int i) {
- if (i<0) return -1;
- if (i>0) return 1;
- return 0;
-}
-```
-
-Get address of function
-
-```c
-printf("fun1 address %016x",&fun1);//64bit platform
-```
-
-### If statement
-
-```c
-if () ;
-if () {}
-```
-
-One of the way to check error of returned functions is
-
-```c
-if ((c = getfun()) == 0) {
-}
-```
-
-Most simplest and outdated way to do this is when getting input from command line
-```c
-#include <stdio.h>
-int main() {
- int c;
- char ch;
- while ((c = getchar()) != EOF ) {
- ch = c;
- printf("Typed character %c\n",c);
- }
-}
-```
-
-### For cycle
-
-For loop is one that may involve some trickery, its
-as simple as
-
-```c
-for (<INITIAL>;<TERMINATE CONDITION>;<AFTER CYCLE>) {
-}
-```
-
-Go over values from 1 till 10
-
-```c
-int i=0;
-for (i=1;i<=10;i++) {
- printf("%d\n",i)
-}
-```
-
-Now lets do it from 10 till 1
-
-```c
-int i=0;
-for (i=10;i>0;i--) {
- printf("%d\n",i)
-}
-```
-
-Now lets make one liner
-
-```c
-for (i=0;i<10;i++,printf("%d\n",i));
-```
-
-Yes there is possible to write as many expressions as needed.
-
-
-### Structure
-
-Structure allows to combine types under one new type. Structure is convenient way how to combine set
-of types and reuse them as one.
-
-```c
-struct struct1 {
- uint8_t a;
- uint16_t b;
- uint32_t c;
- uint64_t d;
-};
-```
-
-Total intuitive size of structure would be
-```c
-int total_szie = sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint64_t);
-int real_size = sizeof(struct1);
-```
-
-Types are placed inside structure to make fast access to them. Some instructions of CPU may require
-to access aligned memory addresses to not have penalty on accessing types inside structure.
-
-To directly mess with alignment of types use attribute
-```c
-__attribute__ ((aligned (8)))
-```
-
-
-Use attributes to pack structure and be not architecture dependent.
-
-```c
-struct struct2 {
- uint8_t a;
- uint16_t b;
- uint32_t c;
- uint64_t d;
-} __attribute__((packed));
-```
-
-Now let check size of structure after it packed
-
-```c
-int new_size = sizeof(struct2);
-```
-
-Also there is possible to add aligmnet to each time in structure
-```c
-struct struct3 {
- uint8_t a __attribute__((aligned (8)));
- uint16_t b __attribute__((aligned (8)));
- uint32_t c __attribute__((aligned (8)));
- uint64_t d __attribute__((aligned (8)));
-} __attribute__((aligned (8)));
-```
-
-Now size of structure will be 32.
-
-All results on amd64, other arch may differ.
-
-### How to shoot leg
-Forget that struct size is not consistent.
-
-### Recursion
-
-Recursion is technique that could be useful to write shorter code
-and deal with cycles. One thing that recursion suffer is that it consumes
-stack memory and its have default limit on platform.
-
-```c
-#include <stdio.h>
-#include <stdlib.h>
-
-int fun_r(int i) {
- printf("val %d\n",i);
- fun_r(i+1);
- return 0;
-}
-
-int main()
-{
- fun_r(0);
-}
-```
-
-Program will fail after its reach out of stack range.
-When increase the default stack limit it go more further.
-
-
-Check default stack size
-
-```
-ulimit -s
-```
-
-Set stack size
-
-```
-ulimit -s 16384
-```
-
-### Macro
-
-There is many things useful as macros. There is many tricks in macros to emit
-useful parts of code.
-
-Define values, as its enum.
-```c
-#define VAL_0 0
-#define VAL_1 1
-#define VAL_LAST VAL_1
-```
-
-Multiline macro
-```c
-#define INC_FUN(TYPE) TYPE inc_##TYPE(a TYPE){\
- TYPE c=1\
- return a + c\
-}
-
-INC_FUN(int)
-INC_FUN(char)
-INC_FUN(double)
-INC_FUN(notype)
-```
-
-to check code expansion of macro run
-
-```
-gcc -E <SOURCE_FILE>
-```
-
-
-
-http://main.lv/writeup/c_macro_tricks.md
-
-
-https://jadlevesque.github.io/PPMP-Iceberg/
-
-
-### Pointers
-
-One the C most loved feature is pointers, they allow to access addresses without any sanity check
-and they dont have any lifetime, so anything is possible with those.
-
-Pointer contains address which is interpreted according of pointer type
-
-```c
-int c;
-int ptr=&c;
-```
-
-Go over array of chars
-```c
-#include <stdio.h>
-#include <stdlib.h>
-
-int main() {
- char s[]="asd";
- char *c=&s;
- while (*c != 0) {
- printf("NExt char %c addr %016x\n",*c,c);
- c++;
- }
-}
-```
-Go over array of ints
-```c
- int i=0;
- int arr[] = {9,7,5,3,1};
- int *ptr = arr;
- while (i<5) {
- printf("Number value %d addr %016x\n",*ptr, ptr);
- ptr++;
- i++;
- }
-```
-
-Pointer arithmetics like +1 will move to next address that is offset of type size.
-As example below structure size is 12, and increment of pointer to that structure
-increment address to sizeof structure. And yes address is pointing to not mapped memory, so it
-will segfault if accessed.
-
-```c
-struct size12 {
- int a,b,c;
-}
-
-int main() {
- struct size12 *s=0;
- s++;
- printf("%016x\n",s);
- s++;
- printf("%016x\n",s);
-}
-```
-
-Double pointers are pointers to pointers
-
-```c
-#include <stdio.h>
-
-int main(int argc, char **argv) {
- char *arg = argv[0];
- printf("Program name %s\n",arg);
-}
-```
-
-#### How to shoot the leg
-Run pointer in while loop incrementing pointer. It will stop only when segfaults.
-
-Dont initialize pointer and it will have random value.
-
-
-
-### Allocate memory
-
-From programs perspective memory allocation is adding address range to executable that can be addressed.
-
-malloc should be accompanied with free statement, otherwise it will have memory leaks.
-
-```c
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-int main() {
- char *c = malloc(16);
- memset(c,0,16);
- int *arr = malloc(16*sizeof(int));
- memset(arr,0,16*sizeof(int));
- free(c);
- free(arr);
-}
-```
-
-### Signed/Unsigned
-
-Signed and unsigned variables differ just in one bit interpretation. But they have different behavior on minimal and maximal values.
-
-
-```c
-#include <stdio.h>
-#include <limits.h>
-int main()
-{
- int i=INT_MAX;
- unsigned int u=UINT_MAX;
-
- printf("i=%d\n",i);
- printf("u=%u\n",u);
-
- i++;
- u++;
- printf("i=%d\n",i);
- printf("u=%u\n",u);
- i=0;
- u=0;
- i--;
- u--;
- printf("i=%d\n",i);
- printf("u=%u\n",u);
-
-}
-```
-
-### Endianess
-
-
-```c
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdint.h>
-
-int main() {
- int arr[4] = {0x00112233,0x44556677,0x8899AABB, 0xCCDDEEFF};
- printf("%08x\n",arr[0]);
- printf("%08x\n",arr[1]);
- printf("%08x\n",arr[2]);
- printf("%08x\n",arr[3]);
-
- FILE *f = fopen("int.hex","w+");
- fprintf(f,"%08x",arr[0]);
- fprintf(f,"%08x",arr[1]);
- fprintf(f,"%08x",arr[2]);
- fprintf(f,"%08x",arr[3]);
- fclose(f);
-
- int fd=open("int.bin",O_CREAT|O_RDWR,S_IWUSR|S_IRUSR|S_IRGRP|S_IRWXO);
- write(fd,arr,sizeof(arr));
- close(fd);
-
- int i;
- fd = open("int.bin2",O_CREAT|O_RDWR,S_IWUSR|S_IRUSR|S_IRGRP|S_IRWXO);
- for (i=0;i<4;i++) {
- uint32_t val = (arr[i]>>16) &0x0000ffff;
- val += (arr[i]<<16)&0xffff0000;
- write(fd,&val,sizeof(uint32_t));
- }
- close(fd);
-}
-```
-
-While saving formated values to file you will get what you expect
-```
-$ cat int.hex
-00112233445566778899aabbccddeeff
-```
-
-Saving just memory dump of all values, will give you different result
-```
-$ hexdump int.bin
-0000000 2233 0011 6677 4455 aabb 8899 eeff ccdd
-0000010
-```
-
-Need to swap 16bit pairs to look same as value memory dump
-```
-$ hexdump int.bin2
-0000000 0011 2233 4455 6677 8899 aabb ccdd eeff
-0000010
-```
-
-### Compiler flags
-
-Compiler have whole list of command line arguments that you can enable for different purposes, lets look into some of them
-https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html
-
-Lets try to apply some of the flags to examples above.
-
-Best starte options is, those will give you more warnings.
-
-```
--Wall -Wextra
-```
-
-Most of the examples here was written in sloppy style, so adding extra checks like will find more issues with code, probably
-all of provided examples will show issues with this extra compiler flags
-
-```
-Wformat-security -Wduplicated-cond -Wfloat-equal -Wshadow -Wconversion -Wjump-misses-init -Wlogical-not-parentheses -Wnull-dereference
-```
-
-To get all macroses expanded in C code add compiler flag. Output will be C source with all macro expansion
-```
--E
-```
-
-Output resulting file not to binary but to generated assembly add
-```
--S
-```
-
-More readable output can be obtained with
-
-```
-gcc FILE.c -Wa,-adhln=FILE.S -g -fverbose-asm -masm=intel
-```
-
-Basic compiler optimisation flags that can speedup program or make it smaller
-
-```
--O -O0 -O1 -O2 -O3 -Os -Ofast -Og -Oz
-```
-
-https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options
-
-https://panthema.net/2013/0124-GCC-Output-Assembler-Code/
-https://blogs.oracle.com/linux/post/making-code-more-secure-with-gcc-part-1
-
-
-### Shared library
-
-Shared library is common way how to reuse big chunks of code.
-
-```c
-#include <stdio.h>
-int fun1() {
- return 1;
-}
-
-int fun2() {
- printf("Function name fun2\n");
-}
-
-int fun3(int a, int b) {
- return a+b;
-}
-```
-
-```
-$ gcc -c lib_share.c
-$ gcc -shared -o lib_share.so libshare.o
-$ ldd lib_share.so
- linux-vdso.so.1 (0x00007ffdb994d000)
- libc.so.6 => /usr/lib/libc.so.6 (0x00007f0c39400000)
- /usr/lib64/ld-linux-x86-64.so.2 (0x00007f0c39835000)
-```
-
-Now lets link to our binary
-```c
-#include <stdio.h>
-
-//functions that are implemented in shared lib
-int fun1();
-int fun2();
-int fun3(int a, int b);
-
-int main() {
- fun1();
- fun2();
- fun3();
-}
-```
-
-```
-$ gcc -L. -lshare use_share.c -o use_share
-./use_share
-./use_share: error while loading shared libraries: libshare.so: cannot open shared object file: No such file or directory
-ldd ./use_share
- linux-vdso.so.1 (0x00007ffedcad5000)
- libshare.so => not found
- libc.so.6 => /usr/lib/libc.so.6 (0x00007f7b99a00000)
- /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f7b99c90000)
-```
-
-Library is not in search path
-```
-$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd`
-$ ./use_share
-$ ldd use_share
- linux-vdso.so.1 (0x00007fffc415c000)
- libshare.so => /your/path/libshare.so (0x00007f48b03c6000)
- libc.so.6 => /usr/lib/libc.so.6 (0x00007f48b0000000)
- /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f48b03d2000)
-```
-
-Other way is to set custom library search location. Lets set it to search in current directory.
-And no need to modify LD_LIBRARY_PATH
-
-```
-$ gcc use_share.c -o use_share -L. -lshare -Wl,-rpath=./
-$ ldd ./use_share
- linux-vdso.so.1 (0x00007fff5c964000)
- libshare.so => ./libshare.so (0x00007f791000f000)
- libc.so.6 => /usr/lib/libc.so.6 (0x00007f790fc00000)
- /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f791001b000)
-```
-
-So now executable runs libshare from local directory. Ofc there is possible to install shared library into systems /usr/lib
-
-### Static library
-
-
-
-
-### Static binary
-
-Static binary don't use any shared libraries, and its possible to built it once and distribute on other platforms
-without need to install dependencies.
-
-
-```c
-#include <stdio.h>
-#include <stdlib.h>
-
-int main(int argc, char **argv) {
- return 0;
-}
-```
-
-First step to compile file and see that is dynamically lined
-```
-$ gcc static_elf.c -o static_elf
-$ file static_elf
-static_elf: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=bc6ac706075874858e1c4a8accf77e704f4ea25a, for GNU/Linux 4.4.0, with debug_info, not stripped
-$ ldd ./static_elf
- linux-vdso.so.1 (0x00007ffccef49000)
- libc.so.6 => /usr/lib/libc.so.6 (0x00007fcbb8800000)
- /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fcbb8b63000)
-
-```
-
-After adding static option we can verify that tools now report it as statically linked. Size of binary increased as all functions
-that require to run executable are now contained in binary.
-
-```
-$ gcc static_elf.c -static -o static_elf
-$ file static_elf
-static_elf: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=c54d2e4d2a3d11fe920bee9a44af045c6f67ab56, for GNU/Linux 4.4.0, with debug_info, not stripped
-$ ldd static_elf
- not a dynamic executable
-```
-
-Statically compiled file should work on most platforms.
-
-
-
-### Atomic
-HERE
-
-### Multithreading
-HERE
-
-
-<!--
-### stdin,stdout,stderr
-### Styles
-
---->
-
-
-
-
-## Basic usage
-
-### File manipulation with libc
-
-Create file open data using libc functions
-
-```c
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-int main() {
- FILE *f = fopen("file.txt","w+");
- char *s = "Hello";
- fwrite(s,1,strlen(s),f);
- fclose(f);
-}
-```
-
-Open file and read data back
-
-```c
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-int main() {
- FILE *f = fopen("file.txt","r");
- char buf[128];
- int r;
- r = fread(buf,1,128,f);
- buf[r] = 0;
- printf("->%s\n",buf,r);
- fclose(f);
-}
-```
-
-### File manipulation with syscalls
-
-Now lets do the same without using libc functions using syscall function to directly use syscalls,
-its also straightforward to rewrite example for assembly.
-
-```c
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/syscall.h>
-#include <string.h>
-
-int main(void) {
- int fd = syscall(SYS_open, "sys.txt", O_CREAT|O_WRONLY, S_IRWXU|S_IRGRP|S_IXGRP);
- char s[] = "hello sycall\n";
- syscall(SYS_write, fd, s, strlen(s));
- syscall(SYS_close, fd);
- return 0;
-}
-```
-
-
-Read data from file
-
-```c
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/syscall.h>
-#include <string.h>
-
-int main(void) {
- int fd = syscall(SYS_open, "sys.txt", O_RDONLY);
- char s[128];
- int r = syscall(SYS_read, fd, s, 128);
- s[r] = 0;
- syscall(SYS_close, fd);
- syscall(SYS_write, 0, s, r);
- return 0;
-}
-```
-
-## Advanced topics
-
-### Kernel module
-
-Linux kernel, macos kernel and *BSD's kernels written in C,
-so there is possibility to write kernel modules in C for some of those.
-
-Example will not match some specific things to local distribution.
-
-```c
-
-```
-
-http://main.lv/writeup/kernel_hello_world.md
-
-### Linking
-
-Linking is one of the most interesting parts of compiling of C code. When object file is created
-it contains functions and variables that can be of different type. And linking tries to resolve
-all of those. So there is possible to have fun with linking and content of object files.
-
-
-First example is piece of C code that can be compiled to object file, but it will not able to
-resolve to executable.
-```
-gcc -c link_elf.c
-```
-```c
-int main() {
- fun1();
- fun2();
-}
-```
-So we can see that fun1 and fun2 are marked as undefined in object file. If we try compile it will not able to find those.
-So lets create one more object file
-```
-$ readelf -a link_elf.o
-
-Symbol table '.symtab' contains 6 entries:
- Num: Value Size Type Bind Vis Ndx Name
- 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
- 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS link_elf.c
- 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 .text
- 3: 0000000000000000 31 FUNC GLOBAL DEFAULT 1 main
- 4: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND fun1
- 5: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND fun2
-
-```
-__link_fun1.c__
-```c
-void fun1() {
- printf("Hello fun1\n");
-}
-void fun2() {
- printf("Hello fun2\n");
-}
-```
-
-So now we have object file with funtions that are defined. and we see that its now have undefine pritnf/puts function there.
-
-```
-readelf -a link_fun1.o
-Symbol table '.symtab' contains 7 entries:
- Num: Value Size Type Bind Vis Ndx Name
- 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
- 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS link_fun1.c
- 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 .text
- 3: 0000000000000000 0 SECTION LOCAL DEFAULT 5 .rodata
- 4: 0000000000000000 22 FUNC GLOBAL DEFAULT 1 fun1
- 5: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts
- 6: 0000000000000016 22 FUNC GLOBAL DEFAULT 1 fun2
-
-```
-
-we can merge both of those files together
-```shell
-gcc -o link_elf link_elf.o link_fun1.o
-```
-The function in object files dont have any idea about input output types. That why anything can be linked that just match name
-lets rewrite code like this
-
-```c
-int fun1(int i) {
- printf("Hello fun1\n");
-}
-int fun2(int i) {
- printf("Hello fun2\n");
-}
-```
-And this links without issue. Theat this as 2 sets that are merge together only few thins know when linking things.
-Return type, and function arguments arent exposed when object file is created.
-
-Functions can have aliases.
-
-__link_fun2.c__
-
-```c
-static void fun2() {
- printf("hello 2\n");
-} __attribute__ ((alias("fun1")));
-```
-
-Now function is local.
-
-```
-Symbol table '.symtab' contains 6 entries:
- Num: Value Size Type Bind Vis Ndx Name
- 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
- 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS link_fun2.c
- 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 .text
- 3: 0000000000000000 0 SECTION LOCAL DEFAULT 5 .rodata
- 4: 0000000000000000 22 FUNC LOCAL DEFAULT 1 fun2
- 5: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts
-```
-
-Lets compile all object to executable. And the function fun2 isnt used in this case,
-
-
-
-```
-$ gcc link_fun1.o link_fun2.o link_elf.o -o link_elf
-$ ./link_elf
-Hello fun1
-Hello fun2
-
-```
-
-
-
-lets witch aliasing between 2 functions **fun2**
-
-
-```
-link_fun1.o
- 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
- 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS link_fun1.c
- 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 .text
- 3: 0000000000000000 0 SECTION LOCAL DEFAULT 5 .rodata
- 4: 000000000000001d 29 FUNC LOCAL DEFAULT 1 fun2
- 5: 0000000000000000 29 FUNC GLOBAL DEFAULT 1 fun1
- 6: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts
-
-link_fun2.o
- 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
- 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS link_fun2.c
- 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 .text
- 3: 0000000000000000 0 SECTION LOCAL DEFAULT 5 .rodata
- 4: 0000000000000000 22 FUNC GLOBAL DEFAULT 1 fun2
- 5: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts
-
-```
-
-```
-$ gcc link_fun1.o link_fun2.o link_elf.o -o link_elf
-$ ./link_elf
-Hello fun1
-hello 2
-```
-
-So all of this plays role in linking object files.
-There is more interesting utilit called ld its doing things on lower level then gcc.
-
-
-### Extern
-
-### Attributes
-PASS
-### Creating shared library
-PASS
-### Create static libraries
-PASS
-### Join all objects together
-PASS
-### Compile with musl
-
-The libc is not the only option as standard c library, there is few others one of them is musl
-
-```
-$ musl-gcc hello_world.c -o hello_world
-$ file ./hello_world
-hello_world_musl: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, not stripped
-```
-
-
-### Inspect elf files
-
-There is few utilities that help to check if elf file is ok.
-
-ldd show what kind of shared libraries elf will try to load
-
-```
-$ ldd hello_world
- linux-vdso.so.1 (0x00007fffcb2ae000)
- libc.so.6 => /usr/lib/libc.so.6 (0x00007ffb80c00000)
- /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007ffb80fb9000)
-
-```
-
-Readelf allows to inspect content of elf files, headers and interpret values in headers.
-In few example above we allready used that feature to check content of compiled objectfiles.
-
-```
-$ readelf -s ./hello_world
-Symbol table '.symtab' contains 37 entries:
- Num: Value Size Type Bind Vis Ndx Name
- 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
- 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS abi-note.c
- 2: 000000000000039c 32 OBJECT LOCAL DEFAULT 4 __abi_tag
- 3: 0000000000000000 0 FILE LOCAL DEFAULT ABS init.c
- 4: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
- 5: 0000000000001070 0 FUNC LOCAL DEFAULT 14 deregister_tm_clones
- 6: 00000000000010a0 0 FUNC LOCAL DEFAULT 14 register_tm_clones
- 7: 00000000000010e0 0 FUNC LOCAL DEFAULT 14 __do_global_dtors_aux
- 8: 0000000000004030 1 OBJECT LOCAL DEFAULT 25 completed.0
- 9: 0000000000003df0 0 OBJECT LOCAL DEFAULT 20 __do_global_dtor[...]
- 10: 0000000000001130 0 FUNC LOCAL DEFAULT 14 frame_dummy
- 11: 0000000000003de8 0 OBJECT LOCAL DEFAULT 19 __frame_dummy_in[...]
- 12: 0000000000000000 0 FILE LOCAL DEFAULT ABS hello_world.c
- 13: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
- 14: 00000000000020b0 0 OBJECT LOCAL DEFAULT 18 __FRAME_END__
- 15: 0000000000000000 0 FILE LOCAL DEFAULT ABS
- 16: 0000000000003df8 0 OBJECT LOCAL DEFAULT 21 _DYNAMIC
- 17: 0000000000002010 0 NOTYPE LOCAL DEFAULT 17 __GNU_EH_FRAME_HDR
- 18: 0000000000004000 0 OBJECT LOCAL DEFAULT 23 _GLOBAL_OFFSET_TABLE_
- 19: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_mai[...]
- 20: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
- 21: 0000000000004020 0 NOTYPE WEAK DEFAULT 24 data_start
- 22: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5
- 23: 0000000000004030 0 NOTYPE GLOBAL DEFAULT 24 _edata
- 24: 0000000000001154 0 FUNC GLOBAL HIDDEN 15 _fini
- 25: 0000000000004020 0 NOTYPE GLOBAL DEFAULT 24 __data_start
- 26: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
- 27: 0000000000004028 0 OBJECT GLOBAL HIDDEN 24 __dso_handle
- 28: 0000000000002000 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used
- 29: 0000000000004038 0 NOTYPE GLOBAL DEFAULT 25 _end
- 30: 0000000000001040 38 FUNC GLOBAL DEFAULT 14 _start
- 31: 0000000000004030 0 NOTYPE GLOBAL DEFAULT 25 __bss_start
- 32: 0000000000001139 26 FUNC GLOBAL DEFAULT 14 main
- 33: 0000000000004030 0 OBJECT GLOBAL HIDDEN 24 __TMC_END__
- 34: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMC[...]
- 35: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@G[...]
- 36: 0000000000001000 0 FUNC GLOBAL HIDDEN 12 _init
-```
-
-### No standard library
-
-Lets write hello world without libc.
-
-__noc.c__
-```c
-void _start() {
-
-}
-```
-
-```
-$ gcc -c noc.c
-$ ld -dynamic-linker /lib/ld-linux.so.2 noc.o -o noc
-$ file noc
-noc: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
-```
-
-Next step to make it more working then segfaulting.
-
-```c
-void _start() {
- asm ( \
- "movl $1,%eax\n" \
- "xor %ebx,%ebx\n" \
- "int $128\n" \
- );
-}
-```
-
-Now this is all about calling the syscalls
-
-Lets print the message
-```c
-signed int write(int fd, const void *buf, unsigned int size)
-{
- signed int ret;
- asm volatile
- (
- "syscall"
- : "=a" (ret)
- // EDI RSI RDX
- : "0"(1), "D"(fd), "S"(buf), "d"(size)
- : "rcx", "r11", "memory"
- );
- return ret;
-}
-
-void _start() {
- write(1,"no libc",8);
- asm ( \
- "movl $1,%eax\n" \
- "xor %ebx,%ebx\n" \
- "int $128\n" \
- );
-}
-```
-
-http://main.lv/writeup/making_c_executables_smaller.md
-
-### Memory leaks
-
-Memory leaks is cruitial part of C language. Default case when they are detected are
-when allocated memory wasn free'd after use. If amount of this type of memory increasing then
-its can eventually fill whole memory and system will be unresponsive. Here is simple example
-how memory leak created and how to detect it.
-
-```c
-#include <stdlib.h>
-
-int main() {
-
- char *ptr = malloc(12);
-
- return 0;
-}
-```
-
-The best way to detect it to use valgrind.
-
-```
-$ valgrind ./malloc
-
-==778== HEAP SUMMARY:
-==778== in use at exit: 12 bytes in 1 blocks
-==778== total heap usage: 2 allocs, 1 frees, 1,036 bytes allocated
-```
-
-There is seen 2 allocs and 1 free. But we see that 12bytes after exit. So our created leak is detected.
-More complex example. So now we created leaking function and we called it 5 times. But in larger code
-base it would be nice to see location of leaks.
-
-```c
-#include <stdlib.h>
-
-int* mem_alloc(int sz) {
- int *ret=NULL;
-
- if (sz < 0) {
- return NULL;
- }
-
- ret = malloc(sz*sizeof(int));
-
- if (sz>10) {
- return NULL;
- }
-
- return ret;
-
-}
-
-int main() {
-
- mem_alloc(0);
-
- free(mem_alloc(1));
-
- mem_alloc(100);
-
- free(mem_alloc(2));
-
- mem_alloc(10);
-
- return 0;
-}
-```
-
-There is 3 blocks that leaks, and we see where its comming from there is possible to guess but it would better
-to have position of where leak located.
-
-```
-valgrind --leak-check=full --track-origins=yes --log-file=log.txt ./memleak2
-
-==4974== HEAP SUMMARY:
-==4974== in use at exit: 440 bytes in 3 blocks
-==4974== total heap usage: 5 allocs, 2 frees, 452 bytes allocated
-==4974==
-==4974== 0 bytes in 1 blocks are definitely lost in loss record 1 of 3
-==4974== at 0x4841888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
-==4974== by 0x109179: mem_alloc (in /home/fam/prog/c/undefined_c/memleak2)
-==4974== by 0x10919E: main (in /home/fam/prog/c/undefined_c/memleak2)
-==4974==
-==4974== 40 bytes in 1 blocks are definitely lost in loss record 2 of 3
-==4974== at 0x4841888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
-==4974== by 0x109179: mem_alloc (in /home/fam/prog/c/undefined_c/memleak2)
-==4974== by 0x1091D6: main (in /home/fam/prog/c/undefined_c/memleak2)
-==4974==
-==4974== 400 bytes in 1 blocks are definitely lost in loss record 3 of 3
-==4974== at 0x4841888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
-==4974== by 0x109179: mem_alloc (in /home/fam/prog/c/undefined_c/memleak2)
-==4974== by 0x1091BA: main (in /home/fam/prog/c/undefined_c/memleak2)
-==4974==
-==4974== LEAK SUMMARY:
-==4974== definitely lost: 440 bytes in 3 blocks
-==4974== indirectly lost: 0 bytes in 0 blocks
-==4974== possibly lost: 0 bytes in 0 blocks
-==4974== still reachable: 0 bytes in 0 blocks
-==4974== suppressed: 0 bytes in 0 blocks
-```
-
-Add compilation option __g3__
-
-```
-gcc -g3 memleak2.c -o memleak2
-```
-
-Now it shows source lines and trace from where the leaking code where called. Thats looks better now.
-
-```
-valgrind --leak-check=full --track-origins=yes --log-file=log.txt ./memleak2
-
-==5073== HEAP SUMMARY:
-==5073== in use at exit: 440 bytes in 3 blocks
-==5073== total heap usage: 5 allocs, 2 frees, 452 bytes allocated
-==5073==
-==5073== 0 bytes in 1 blocks are definitely lost in loss record 1 of 3
-==5073== at 0x4841888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
-==5073== by 0x109179: mem_alloc (memleak2.c:10)
-==5073== by 0x10919E: main (memleak2.c:22)
-==5073==
-==5073== 40 bytes in 1 blocks are definitely lost in loss record 2 of 3
-==5073== at 0x4841888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
-==5073== by 0x109179: mem_alloc (memleak2.c:10)
-==5073== by 0x1091D6: main (memleak2.c:30)
-==5073==
-==5073== 400 bytes in 1 blocks are definitely lost in loss record 3 of 3
-==5073== at 0x4841888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
-==5073== by 0x109179: mem_alloc (memleak2.c:10)
-==5073== by 0x1091BA: main (memleak2.c:26)
-==5073==
-==5073== LEAK SUMMARY:
-==5073== definitely lost: 440 bytes in 3 blocks
-==5073== indirectly lost: 0 bytes in 0 blocks
-==5073== possibly lost: 0 bytes in 0 blocks
-==5073== still reachable: 0 bytes in 0 blocks
-==5073== suppressed: 0 bytes in 0 blocks
-==5073==
-```
-
-
-### Code coverage
-
-Compile file with extra flags and generate gcov file output.
-Ther is only one branch not used. Coverage should show with part isnt used.
-
-```c
-#include <stdio.h>
-
-int fun1(int a) {
- if (a < 0) {
- printf("Smaller then zero\n");
- }
- if (a==0) {
- printf("Equails to zero\n");
- }
- if (a>0) {
- printf("Bigger then zero\n");
- }
-}
-
-int main() {
-
- printf("Start\n");
- fun1(0);
- fun1(1);
-
- return 0;
-}
-```
-
-```
-$ gcc -fprofile-arcs -ftest-coverage coverage.c -o coverage
-$ gcov ./coverage
-File 'coverage.c'
-Lines executed:92.31% of 13
-Creating 'coverage.c.gcov'
-
-Lines executed:92.31% of 13
-
-```
-
-Gcov file content. So we scant see with line wasnt executed.
-
-```c
- -: 0:Source:coverage.c
- -: 0:Graph:coverage.gcno
- -: 0:Data:coverage.gcda
- -: 0:Runs:1
- -: 1:#include <stdio.h>
- -: 2:
- 2: 3:int fun1(int a) {
- 2: 4: if (a < 0) {
- #####: 5: printf("Smaller then zero\n");
- -: 6: }
- 2: 7: if (a==0) {
- 1: 8: printf("Equails to zero\n");
- -: 9: }
- 2: 10: if (a>0) {
- 1: 11: printf("Bigger then zero\n");
- -: 12: }
- 2: 13:}
- -: 14:
- 1: 15:int main() {
- -: 16:
- 1: 17: printf("Start\n");
- 1: 18: fun1(0);
- 1: 19: fun1(1);
- -: 20:
- 1: 21: return 0;
- -: 22:}
-```
-
-### Profiling
-
-Some parts of code can take substantial amount of time and those parts need to be identified.
-
-```c
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-void slow_sin() {
- float r=0.0f;
- for (int i=0;i<10000000;i++) {
- r += sinf(M_PI/8);
- }
-}
-
-void slower_sin() {
- double r=0.0f;
- for (int i=0;i<10000000;i++) {
- r += sin(M_PI/8);
- }
-}
-
-void fast_sin() {
- float pre_calc = sinf(M_PI/8);
- float r = 0.0f;
- for (int i=0;i<10000000;i++) {
- r += pre_calc;
- }
-}
-
-int main() {
- slow_sin();
- slower_sin();
- fast_sin();
-}
-```
-
-Compile and rung with profiling
-
-```
-gcc -pg perf_speed.c -o perf_speed -lm
-./perf_speed
-gprof perf_speed gmon.cov
-```
-
-### Sanitizer
-
-C as a greate language have good features in standart such as undefined behaviour. And
-also there is possible to overwrite any data you whant with your code. One of the favorite
-mistake is to write some buffer overruns. Its possible to catch this type of errors with
-stack protection
-
-So in code belove there is possible to write in to array of size 8 more then 8 characters. This is because the is no any boundry check.
-C runtime will be able to detect this kind of things.
-
-
-```c
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-void fun(char *str,int size) {
- char local_var[8];
- memcpy(local_var, str, size);
- printf("Whats inside a stack? %s\n",local_var);
-}
-
-int main() {
- char some_str1[] = "Hello!";
- char some_str2[] = "Hello all!!!";
-
- fun(some_str1,strlen(some_str1));
- fun(some_str2,strlen(some_str2));
-}
-```
-
-```
-Whats inside a stack? Hello!
-Whats inside a stack? Hello all!!!
-*** stack smashing detected ***: terminated
-fish: Job 1, './stack_overrun' terminated by signal SIGABRT (Abort)
-```
-
-If this isnt happening there is possible to add __-fstack-protector__ to compile flags.
-
-C have whole list of undefined behaviours incorporated in standard
-https://en.cppreference.com/w/c/language/behavior
-
-
-
-functions __f__ variable __a__ isnt initialized so its undefined behaviour but there still will be some value. Run few
-times and each time it returns new value when __f(0)__.
-```c
-#include <stdio.h>
-
-size_t f(int x)
-{
- size_t a;
- if(x) // either x nonzero or UB
- a = 42;
- return a;
-}
-
-int main() {
- printf("%d\n",f(0));
- printf("%d\n",f(1));
- printf("%d\n",f(42));
-}
-```
-
-Division by zero. Function __f__ dont check if divisor is 0. Programm going to abort.
-add flag __-fsanitize=integer-divide-by-zero__ and it will be detected at runtime
-
-```c
-#include <stdio.h>
-
-size_t f(int x)
-{
- return 10/x;
-}
-
-int main() {
- printf("%d\n",f(0));
- printf("%d\n",f(1));
- printf("%d\n",f(42));
-}
-```
-
-```
-undefined_b.c:5:14: runtime error: division by zero
-fish: Job 1, './undefined_b' terminated by signal SIGFPE (Floating point exception)
-```
-
-<!--
-### FARMA-C
---->
-
-
-
-
-### Write plugins
-### Preload library
-
-
-## Embedding C
-
-Most of the programming languages support embeding C. As C language have where simple
-functiong naming when its mangled to object format it makes it easy target when
-linking with other languages. Most of other languages have incompatible naming for
-functions when compiled to binary.
-
-### Embed in C++
-
-__lib.h__
-```c
-#include <stdlib.h>
-#include <stdio.h>
-
-int fun_secret_1();
-```
-
-__lib.c__
-```c
-#include "lib.h"
-
-int fun_secret_1() {
- printf("Hello from C\n");
- return -1;
-}
-```
-
-First thing to notice is when file is compiled with C++ is that the name of the function are in different format
-then when its compiled with C.
-```
-$ g++ -c lib.c
-$ readelf -s lib.o
-Symbol table '.symtab' contains 6 entries:
- Num: Value Size Type Bind Vis Ndx Name
- 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
- 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS lib.c
- 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 .text
- 3: 0000000000000000 0 SECTION LOCAL DEFAULT 5 .rodata
- 4: 0000000000000000 26 FUNC GLOBAL DEFAULT 1 _Z12fun_secret_1v
- 5: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts
-
-```
-
-Lets tell C++ that file is C language by adding **extern "c"**
-
-__lib.h__
-```c
-#include <stdlib.h>
-#include <stdio.h>
-
-extern "C" {
-
-int fun_secret_1();
-
-}
-```
-
-__lib.c__
-```c
-#include "lib.h"
-
-extern "C" {
-
-int fun_secret_1() {
- printf("Hello from C\n");
- return -1;
-}
-
-}
-```
-
-Now compiled object file have C function names.
-
-```
-$ g++ lib.c -c
-$ readelf -s lib.o
-
-Symbol table '.symtab' contains 6 entries:
- Num: Value Size Type Bind Vis Ndx Name
- 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
- 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS lib.c
- 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 .text
- 3: 0000000000000000 0 SECTION LOCAL DEFAULT 5 .rodata
- 4: 0000000000000000 26 FUNC GLOBAL DEFAULT 1 fun_secret_1
- 5: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts
-
-```
-
-__cppembed.cpp___
-```cpp
-#include "lib.h"
-
-int main() {
- fun_secret_1();
-}
-```
-
-Doing oposite way running C++ from C
-[/writeup/wraping_c_plus_plus_exceptions_templates_and_classes_in_c.md](/writeup/wraping_c_plus_plus_exceptions_templates_and_classes_in_c.md)
-
-### Embed in Go
-
-__lib.h__
-```c
-#include <stdlib.h>
-#include <stdio.h>
-
-int fun_secret_1();
-```
-__lib.c__
-```c
-#include "lib.h"
-
-int fun_secret_1() {
- printf("Hello from C\n");
- return -1;
-}
-```
-
-__main.go__
-```go
-package main
-// #cgo CFLAGS: -g -Wall
-// #include <stdlib.h>
-// #include "lib.h"
-import "C"
-import (
- "fmt"
-
-)
-func main() {
- fmt.Println("Start program")
- C.fun_secret_1()
- fmt.Println("End program")
-}
-```
-
-```
-go build
-```
-
-[https://karthikkaranth.me/blog/calling-c-code-from-go/](https://karthikkaranth.me/blog/calling-c-code-from-go/)
-
-
-### Embed in Swift
-
-[/writeup/linux_hello_world_in_swift.md](/writeup/linux_hello_world_in_swift.md)
-
-### Embed in Rust
-
-__lib.c__
-```c
-#include <stdio.h>
-#include <stdlib.h>
-
-int fun_secret_1() {
- printf("Hello from C\n");
- return -1;
-}
-```
-
-```rust
-extern "C" {
- fn fun_secret_1();
-}
-
-//rustc main.rs -o hello
-fn main() {
- println!("Start program");
- unsafe {fun_secret_1()}
- println!("End program");
-}
-```
-
-Compile with
-
-```
-gcc -c lib.c
-gcc -shared lib.o -o liblib.so
-rustc main.rs -l lib -L . -o hello -C link-arg="-Wl,-rpath=./"
-```
-
-[https://dev.to/xphoniex/how-to-call-c-code-from-rust-56do](https://dev.to/xphoniex/how-to-call-c-code-from-rust-56do)
-
-### Lua in C
-
-[/writeup/embedding_lua_in_c.md](/writeup/embedding_lua_in_c.md)
-
-### Python in C
-
-
-
-## Multiplatform
-
-### Different flags
-
-### Check architecture
-
-
-
-```c
-```
-
-### AArch64
-
-https://snapshots.linaro.org/gnu-toolchain/13.0-2022.08-1/aarch64-linux-gnu/
-
-download any of the version of gcc and extract
-
-Add bin directory location to env variable PATH
-
-```
-export PATH=$PATH:`pwd`
-```
-
-___main.c__
-```c
-#include <stdio.h>
-
-int main() {
- printf("Hello world arm64\n");
-}
-```
-
-```
-$ arch64-linux-gnu-gcc main.c -o main
-$ ./main
-qemu-aarch64: Could not open '/lib/ld-linux-aarch64.so.1': No such file or directory
-$ file ./main
-./main: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=12448d90030e2ad23dbe6b7bc82a4fa7b7de9659, for GNU/Linux 3.7.0, with debug_info, not stripped
-```
-
-Download sysroot image from linaro page.
-With running
-
-```
-strace ./main
-```
-
-It showed that searched path for libraries are in
-
-```
-/usr/gnemul/qemu-aarch64/lib/
-```
-
-Found missing libc and ld-linux-aarch64 inside sysroot archive and copied at searched location amd now AArch64 binary is running.
-
-```
-$ ./main
-Hello world arm64
-```
-
-### AVR8
-
-AVR is 8bit CPU that is quite popular for hobbiest. As baremetal device its doesnt have full libc support,
-and needs some setup before its possible to do basics things with it.
-
-__avr_echo.c__
-```c
-#include <avr/io.h>
-
-#define FOSC 16000000UL
-#define BAUD 9600
-#define MYUBRR FOSC/16/BAUD-1
-
-void USART_Init( unsigned int ubrr)
-{
- UBRRH = (unsigned char)(ubrr>>8);
- UBRRL = (unsigned char)ubrr;
- UCSRB = (1<<RXEN)|(1<<TXEN);
- UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
-}
-
-int main()
-{
- char c;
- USART_Init( MYUBRR );
- while(1)
- {
- while ( !(UCSRA & (1<<RXC))){};
- c = UDR;
- while (!(UCSRA & (1<<UDRE))){};
- UDR = c;
- }
- return 0;
-}
-```
-
-```
-avr-gcc avr_echo.c -mmcu=atmega16 -Wall -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -o avr_echo.out
-```
-
-Next steps woule be to programm it, in case you have ISPv2 programmer and ATmega16 chip
-
-```bash
-avr-objdump -s --disassemble avr_echo.out > avr_echo.s
-avr-objcopy -j .text -O ihex avr_echo.out avr_echo.hex
-avrdude -pm16 -cavrispv2 -Pusb -U flash:w:avr_echo.hex
-```
-
-### Emscripten
-
-[/writeup/web_assembly_sdl_example.md](/writeup/web_assembly_sdl_example.md)
-
-
-
-
-
-
-