2

I'm reading a book on coding an operating system and I'm writing the C code examples they have in the book and compiling and testing the code in the terminal but I ran into a problem with this code.

The file with this code in it is named "hello.c". I compiled the file with "gcc hello.c -o hello" and then ran it with "./hello".

I received the message Segmentation fault (core dumped), and I'm unsure of what I'm doing wrong.

#include <stdio.h>

void preinit1() {
  printf("%s\n", __FUNCTION__);
}

void preinit2() {
  printf("%s\n", __FUNCTION__);
}

void init1() {
  printf("%s\n", __FUNCTION__);
}

void init2() {
  printf("%s\n", __FUNCTION__);
}

typedef void (*preinit)();
typedef void (*init)();

__attribute__((section(".init_array"))) preinit
  preinit_arr[2] = {preinit1, preinit2};

__attribute__((section(".init_array"))) init
  init_arr[2] = {init1, init2};

int main(int argc, char *argv[])
{
    printf("hello world!\n");

    return 0;
}
Cryoexn
  • 97
  • 1
  • 1
  • 8
  • https://ericlippert.com/2014/03/05/how-to-debug-small-programs/ https://stackoverflow.com/questions/2069367/how-to-debug-using-gdb – Yunnosch Mar 24 '19 at 22:02
  • 2
    Is `stdout` initialized when the various initialization functions are called, or are they called before the system library is initialized? Have you tried using `write(0, __FUNCTION__, strlen(__FUNCTION__));` instead of `printf()`? (That omits the newlines; they're a nicety that can be foregone, temporarily.) – Jonathan Leffler Mar 24 '19 at 22:07

1 Answers1

2

I don't think you're supposed to add arrays to the section (you've an error in the example, initializing the .init_array twice).

__attribute__((section(".preinit_array"))) preinit preinit_arr1 = preinit1;
__attribute__((section(".preinit_array"))) preinit preinit_arr2 = preinit2;

__attribute__((section(".init_array"))) init init_arr1 = init1;
__attribute__((section(".init_array"))) init init_arr2 = init2;

This is the section declared using arrays

objdump -s -j .init_array hello.orig 

hello.orig:     file format elf64-x86-64

Contents of section .init_array:
 3dc0 30110000 00000000 00000000 00000000  0...............
 3dd0 35110000 00000000 48110000 00000000  5.......H.......
 3de0 5b110000 00000000 6e110000 00000000  [.......n.......

This is the section that works

objdump -s -j .init_array hello

hello:     file format elf64-x86-64

Contents of section .init_array:
 3dc8 30110000 00000000 35110000 00000000  0.......5.......
 3dd8 48110000 00000000 5b110000 00000000  H.......[.......
 3de8 6e110000 00000000                    n.......

In the former there's the null pointer at 3dc8 that probably cause the segmentation (see below), I have no idea why is there maybe somebody other can explain.

(gdb) bt
#0  0x0000000000000000 in ?? ()
#1  0x00005555555551f5 in __libc_csu_init ()
#2  0x00007ffff7dec02a in __libc_start_main (main=0x555555555181 <main>, argc=1, argv=0x7fffffffe1f8, init=0x5555555551b0 <__libc_csu_init>, 
    fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe1e8) at ../csu/libc-start.c:264
#3  0x000055555555507a in _start ()

Fixing only the typo about .preinit_array make the preinit calls work but not the init

Alex
  • 3,264
  • 1
  • 25
  • 40
  • Changing these from arrays worked. I don't know why they have it in the book as arrays but when I changed them I got the same output as the book shows. Thank you. – Cryoexn Mar 24 '19 at 22:55
  • Weird, books examples are supposed to work, maybe something changed with gcc and how it layout the array in the section – Alex Mar 24 '19 at 23:00
  • I just looked at the book again after thinking about what you said. They show in the book code that you are supposed to add the arrays into the `.init_array` section but before the code they say to use the `.preinit_array` section. so it was a book typo but without you mentioning not being able to add arrays to that section I wouldn't have noticed.) – Cryoexn Mar 24 '19 at 23:06