Subversion Repositories QNX 8.QNX8 IFS tool

Rev

Rev 10 | Rev 12 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 10 Rev 11
Line 10... Line 10...
10
#include <sys/stat.h>
10
#include <sys/stat.h>
11
#include <ctype.h>
11
#include <ctype.h>
12
#include <time.h>
12
#include <time.h>
13
 
13
 
14
 
14
 
-
 
15
// compiler-specific glue
15
#ifdef _MSC_VER
16
#ifdef _MSC_VER
16
#include <io.h>
17
#include <io.h>
17
#define __x86_64__ 1
18
#define __x86_64__ 1
18
#define __ORDER_BIG_ENDIAN__    4321
19
#define __ORDER_BIG_ENDIAN__    4321
19
#define __ORDER_LITTLE_ENDIAN__ 1234
20
#define __ORDER_LITTLE_ENDIAN__ 1234
Line 33... Line 34...
33
#define access(p,m) _access ((p), (m))
34
#define access(p,m) _access ((p), (m))
34
#define MAXPATHLEN 1024
35
#define MAXPATHLEN 1024
35
#ifndef thread_local
36
#ifndef thread_local
36
#define thread_local __declspec(thread) // the thread_local keyword wasn't defined before C++11 and C23
37
#define thread_local __declspec(thread) // the thread_local keyword wasn't defined before C++11 and C23
37
#endif // !thread_local
38
#endif // !thread_local
-
 
39
#define START_OF_PACKED_STRUCT() __pragma(pack(push)) __pragma(pack(1))
-
 
40
#define END_OF_PACKED_STRUCT() __pragma(pack(pop))
-
 
41
#define PACKED(thing) thing
38
#else // !_MSC_VER
42
#else // !_MSC_VER
39
#include <sys/param.h>
43
#include <sys/param.h>
40
#include <unistd.h>
44
#include <unistd.h>
41
#ifndef thread_local
45
#ifndef thread_local
42
#define thread_local __thread // the thread_local keyword wasn't defined before C++11 and C23
46
#define thread_local __thread // the thread_local keyword wasn't defined before C++11 and C23
43
#endif // !thread_local
47
#endif // !thread_local
-
 
48
#define START_OF_PACKED_STRUCT()
-
 
49
#define END_OF_PACKED_STRUCT()
-
 
50
#define PACKED(thing) thing __attribute__((packed))
44
#endif // _MSC_VER
51
#endif // _MSC_VER
45
 
52
 
46
 
53
 
47
// handy macros that generate a version number in the format "YYYYMMDD" corresponding to the build date. Usage: printf ("version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD);
54
// handy macros that generate a version number in the format "YYYYMMDD" corresponding to the build date. Usage: printf ("version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD);
48
#ifndef VERSION_ARG_YYYYMMDD
55
#ifndef VERSION_ARG_YYYYMMDD
49
#define BUILDDATE_YEAR  (&__DATE__[7]) // compiler will optimize this into a const string, e.g. "2021"
56
#define BUILDDATE_YEAR  (&__DATE__[7]) // compiler will optimize this into a const string, e.g. "2021"
-
 
57
#define BUILDDATE_MONTH ( \
50
#define BUILDDATE_MONTH (*((uint32_t *) __DATE__) == *((uint32_t *) "Jan ") ? "01" : \
58
   *((uint32_t *) __DATE__) == *((uint32_t *) "Jan ") ? "01" : \
51
                         (*((uint32_t *) __DATE__) == *((uint32_t *) "Feb ") ? "02" : \
59
   *((uint32_t *) __DATE__) == *((uint32_t *) "Feb ") ? "02" : \
52
                          (*((uint32_t *) __DATE__) == *((uint32_t *) "Mar ") ? "03" : \
60
   *((uint32_t *) __DATE__) == *((uint32_t *) "Mar ") ? "03" : \
53
                           (*((uint32_t *) __DATE__) == *((uint32_t *) "Apr ") ? "04" : \
61
   *((uint32_t *) __DATE__) == *((uint32_t *) "Apr ") ? "04" : \
54
                            (*((uint32_t *) __DATE__) == *((uint32_t *) "May ") ? "05" : \
62
   *((uint32_t *) __DATE__) == *((uint32_t *) "May ") ? "05" : \
55
                             (*((uint32_t *) __DATE__) == *((uint32_t *) "Jun ") ? "06" : \
63
   *((uint32_t *) __DATE__) == *((uint32_t *) "Jun ") ? "06" : \
56
                              (*((uint32_t *) __DATE__) == *((uint32_t *) "Jul ") ? "07" : \
64
   *((uint32_t *) __DATE__) == *((uint32_t *) "Jul ") ? "07" : \
57
                               (*((uint32_t *) __DATE__) == *((uint32_t *) "Aug ") ? "08" : \
65
   *((uint32_t *) __DATE__) == *((uint32_t *) "Aug ") ? "08" : \
58
                                (*((uint32_t *) __DATE__) == *((uint32_t *) "Sep ") ? "09" : \
66
   *((uint32_t *) __DATE__) == *((uint32_t *) "Sep ") ? "09" : \
59
                                 (*((uint32_t *) __DATE__) == *((uint32_t *) "Oct ") ? "10" : \
67
   *((uint32_t *) __DATE__) == *((uint32_t *) "Oct ") ? "10" : \
60
                                  (*((uint32_t *) __DATE__) == *((uint32_t *) "Nov ") ? "11" : \
68
   *((uint32_t *) __DATE__) == *((uint32_t *) "Nov ") ? "11" : \
61
                                   (*((uint32_t *) __DATE__) == *((uint32_t *) "Dec ") ? "12" : "XX")))))))))))) // compiler will optimize this into a const string, e.g. "11"
69
   *((uint32_t *) __DATE__) == *((uint32_t *) "Dec ") ? "12" : \
-
 
70
   "XX" \
-
 
71
) // compiler will optimize this into a const string, e.g. "11"
-
 
72
#define BUILDDATE_DAY ( \
62
#define BUILDDATE_DAY   (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  1 ") ? "01" : \
73
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  1 ") ? "01" : \
63
                         (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  2 ") ? "02" : \
74
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  2 ") ? "02" : \
64
                          (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  3 ") ? "03" : \
75
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  3 ") ? "03" : \
65
                           (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  4 ") ? "04" : \
76
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  4 ") ? "04" : \
66
                            (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  5 ") ? "05" : \
77
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  5 ") ? "05" : \
67
                             (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  6 ") ? "06" : \
78
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  6 ") ? "06" : \
68
                              (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  7 ") ? "07" : \
79
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  7 ") ? "07" : \
69
                               (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  8 ") ? "08" : \
80
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  8 ") ? "08" : \
70
                                (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  9 ") ? "09" : \
81
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  9 ") ? "09" : \
71
                                 (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 10 ") ? "10" : \
82
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 10 ") ? "10" : \
72
                                  (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 11 ") ? "11" : \
83
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 11 ") ? "11" : \
73
                                   (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 12 ") ? "12" : \
84
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 12 ") ? "12" : \
74
                                    (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 13 ") ? "13" : \
85
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 13 ") ? "13" : \
75
                                     (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 14 ") ? "14" : \
86
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 14 ") ? "14" : \
76
                                      (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 15 ") ? "15" : \
87
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 15 ") ? "15" : \
77
                                       (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 16 ") ? "16" : \
88
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 16 ") ? "16" : \
78
                                        (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 17 ") ? "17" : \
89
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 17 ") ? "17" : \
79
                                         (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 18 ") ? "18" : \
90
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 18 ") ? "18" : \
80
                                          (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 19 ") ? "19" : \
91
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 19 ") ? "19" : \
81
                                           (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 20 ") ? "20" : \
92
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 20 ") ? "20" : \
82
                                            (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 21 ") ? "21" : \
93
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 21 ") ? "21" : \
83
                                             (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 22 ") ? "22" : \
94
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 22 ") ? "22" : \
84
                                              (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 23 ") ? "23" : \
95
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 23 ") ? "23" : \
85
                                               (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 24 ") ? "24" : \
96
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 24 ") ? "24" : \
86
                                                (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 25 ") ? "25" : \
97
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 25 ") ? "25" : \
87
                                                 (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 26 ") ? "26" : \
98
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 26 ") ? "26" : \
88
                                                  (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 27 ") ? "27" : \
99
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 27 ") ? "27" : \
89
                                                   (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 28 ") ? "28" : \
100
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 28 ") ? "28" : \
90
                                                    (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 29 ") ? "29" : \
101
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 29 ") ? "29" : \
91
                                                     (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 30 ") ? "30" : \
102
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 30 ") ? "30" : \
92
                                                      (*((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 31 ") ? "31" : "XX"))))))))))))))))))))))))))))))) // compiler will optimize this into a const string, e.g. "14"
103
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 31 ") ? "31" : \
-
 
104
   "XX" \
-
 
105
) // compiler will optimize this into a const string, e.g. "14"
93
#define VERSION_FMT_YYYYMMDD "%04s%02s%02s"
106
#define VERSION_FMT_YYYYMMDD "%04s%02s%02s"
94
#define VERSION_ARG_YYYYMMDD BUILDDATE_YEAR, BUILDDATE_MONTH, BUILDDATE_DAY
107
#define VERSION_ARG_YYYYMMDD BUILDDATE_YEAR, BUILDDATE_MONTH, BUILDDATE_DAY
95
#endif // !VERSION_ARG_YYYYMMDD
108
#endif // !VERSION_ARG_YYYYMMDD
96
 
109
 
97
 
110
 
98
// we don't mind about this macro's efficiency...
111
// macro to bring __FILE_NAME__ support to moronic compilers
-
 
112
#ifndef __FILE_NAME__ // Clang 9+ has the macro, GCC 12+ added it too in 2021, MSVC obviously won't do it. Heh.
-
 
113
#define __FILE_NAME__ ( \
-
 
114
   (sizeof (__FILE__) >  2) && (__FILE__[sizeof (__FILE__) -  2] == '/') ? &__FILE__[sizeof (__FILE__) -  1] : \
-
 
115
   (sizeof (__FILE__) >  3) && (__FILE__[sizeof (__FILE__) -  3] == '/') ? &__FILE__[sizeof (__FILE__) -  2] : \
-
 
116
   (sizeof (__FILE__) >  4) && (__FILE__[sizeof (__FILE__) -  4] == '/') ? &__FILE__[sizeof (__FILE__) -  3] : \
-
 
117
   (sizeof (__FILE__) >  5) && (__FILE__[sizeof (__FILE__) -  5] == '/') ? &__FILE__[sizeof (__FILE__) -  4] : \
-
 
118
   (sizeof (__FILE__) >  6) && (__FILE__[sizeof (__FILE__) -  6] == '/') ? &__FILE__[sizeof (__FILE__) -  5] : \
-
 
119
   (sizeof (__FILE__) >  7) && (__FILE__[sizeof (__FILE__) -  7] == '/') ? &__FILE__[sizeof (__FILE__) -  6] : \
-
 
120
   (sizeof (__FILE__) >  8) && (__FILE__[sizeof (__FILE__) -  8] == '/') ? &__FILE__[sizeof (__FILE__) -  7] : \
-
 
121
   (sizeof (__FILE__) >  9) && (__FILE__[sizeof (__FILE__) -  9] == '/') ? &__FILE__[sizeof (__FILE__) -  8] : \
-
 
122
   (sizeof (__FILE__) > 10) && (__FILE__[sizeof (__FILE__) - 10] == '/') ? &__FILE__[sizeof (__FILE__) -  9] : \
-
 
123
   (sizeof (__FILE__) > 11) && (__FILE__[sizeof (__FILE__) - 11] == '/') ? &__FILE__[sizeof (__FILE__) - 10] : \
-
 
124
   (sizeof (__FILE__) > 12) && (__FILE__[sizeof (__FILE__) - 12] == '/') ? &__FILE__[sizeof (__FILE__) - 11] : \
-
 
125
   (sizeof (__FILE__) > 13) && (__FILE__[sizeof (__FILE__) - 13] == '/') ? &__FILE__[sizeof (__FILE__) - 12] : \
-
 
126
   (sizeof (__FILE__) > 14) && (__FILE__[sizeof (__FILE__) - 14] == '/') ? &__FILE__[sizeof (__FILE__) - 13] : \
-
 
127
   (sizeof (__FILE__) > 15) && (__FILE__[sizeof (__FILE__) - 15] == '/') ? &__FILE__[sizeof (__FILE__) - 14] : \
-
 
128
   (sizeof (__FILE__) > 16) && (__FILE__[sizeof (__FILE__) - 16] == '/') ? &__FILE__[sizeof (__FILE__) - 15] : \
-
 
129
   (sizeof (__FILE__) > 17) && (__FILE__[sizeof (__FILE__) - 17] == '/') ? &__FILE__[sizeof (__FILE__) - 16] : \
-
 
130
   (sizeof (__FILE__) > 18) && (__FILE__[sizeof (__FILE__) - 18] == '/') ? &__FILE__[sizeof (__FILE__) - 17] : \
99
#define __FILENAME__ (strrchr (__FILE__, '\\') ? strrchr (__FILE__, '\\') + 1 : (strrchr (__FILE__, '/') ? strrchr (__FILE__, '/') + 1 : __FILE__))
131
   (sizeof (__FILE__) > 19) && (__FILE__[sizeof (__FILE__) - 19] == '/') ? &__FILE__[sizeof (__FILE__) - 18] : \
-
 
132
   (sizeof (__FILE__) > 20) && (__FILE__[sizeof (__FILE__) - 20] == '/') ? &__FILE__[sizeof (__FILE__) - 19] : \
-
 
133
   (sizeof (__FILE__) > 21) && (__FILE__[sizeof (__FILE__) - 21] == '/') ? &__FILE__[sizeof (__FILE__) - 20] : \
-
 
134
   (sizeof (__FILE__) > 22) && (__FILE__[sizeof (__FILE__) - 22] == '/') ? &__FILE__[sizeof (__FILE__) - 21] : \
-
 
135
   (sizeof (__FILE__) > 23) && (__FILE__[sizeof (__FILE__) - 23] == '/') ? &__FILE__[sizeof (__FILE__) - 22] : \
-
 
136
   (sizeof (__FILE__) > 24) && (__FILE__[sizeof (__FILE__) - 24] == '/') ? &__FILE__[sizeof (__FILE__) - 23] : \
-
 
137
   (sizeof (__FILE__) > 25) && (__FILE__[sizeof (__FILE__) - 25] == '/') ? &__FILE__[sizeof (__FILE__) - 24] : \
-
 
138
   (sizeof (__FILE__) > 26) && (__FILE__[sizeof (__FILE__) - 26] == '/') ? &__FILE__[sizeof (__FILE__) - 25] : \
-
 
139
   (sizeof (__FILE__) > 27) && (__FILE__[sizeof (__FILE__) - 27] == '/') ? &__FILE__[sizeof (__FILE__) - 26] : \
-
 
140
   (sizeof (__FILE__) > 28) && (__FILE__[sizeof (__FILE__) - 28] == '/') ? &__FILE__[sizeof (__FILE__) - 27] : \
-
 
141
   (sizeof (__FILE__) > 29) && (__FILE__[sizeof (__FILE__) - 29] == '/') ? &__FILE__[sizeof (__FILE__) - 28] : \
-
 
142
   (sizeof (__FILE__) > 30) && (__FILE__[sizeof (__FILE__) - 30] == '/') ? &__FILE__[sizeof (__FILE__) - 29] : \
-
 
143
   (sizeof (__FILE__) > 31) && (__FILE__[sizeof (__FILE__) - 31] == '/') ? &__FILE__[sizeof (__FILE__) - 30] : \
-
 
144
   (sizeof (__FILE__) > 32) && (__FILE__[sizeof (__FILE__) - 32] == '/') ? &__FILE__[sizeof (__FILE__) - 31] : \
-
 
145
   (sizeof (__FILE__) > 33) && (__FILE__[sizeof (__FILE__) - 33] == '/') ? &__FILE__[sizeof (__FILE__) - 32] : \
-
 
146
   __FILE__) // this *COMPILE-TIME* macro complements the __FILE__ macro defined by the C standard by returning just the filename portion of the full path. Supports filenames up to 32 chars. Expand as necessary.
-
 
147
#endif // !__FILE_NAME__
100
 
148
 
101
 
149
 
102
// exit less brutally than with abort() if something doesn't go the way we'd like to
150
// macro to exit less brutally than with abort() if something doesn't go the way we'd like to
103
#define WELLMANNERED_ASSERT(is_is_true,...) do { if (!(is_is_true)) { fprintf (stderr, "ifstool: fatal error: assertion within %s() in %s line %d failed: ", __FUNCTION__, __FILENAME__, __LINE__); fprintf (stderr, __VA_ARGS__); fputc ('\n', stderr); exit (1); } } while (0)
151
#define WELLMANNERED_ASSERT(is_is_true,...) do { if (!(is_is_true)) { fprintf (stderr, "ifstool: fatal error: consistency check in %s() at %s line %d failed: ", __FUNCTION__, __FILE_NAME__, __LINE__); fprintf (stderr, __VA_ARGS__); fputc ('\n', stderr); exit (1); } } while (0)
104
 
152
 
105
 
153
 
106
// checked read/write/seek operations
154
// macros for checked read/write/seek operations
107
#define fseek_or_die(fp,pos,mode) do { if (fseek ((fp), (pos), (mode)) != 0) { fprintf (stderr, "ifstool: fatal error: fseek() failure within %s() in %s line %d: errno %d (%s)\n", __FUNCTION__, __FILENAME__, __LINE__, errno, strerror (errno)); exit (1); } } while (0)
155
#define fseek_or_die(fp,pos,mode) WELLMANNERED_ASSERT (fseek ((fp), (pos), (mode)) == 0, "fseek() failed with errno %d (%s)", errno, strerror (errno))
108
#define fread_or_die(buf,sz,len,fp) do { if (fread ((buf), (sz), (len), (fp)) != (len)) { fprintf (stderr, "ifstool: fatal error: fread() failure within %s() in %s line %d: errno %d (%s)\n", __FUNCTION__, __FILENAME__, __LINE__, errno, strerror (errno)); exit (1); } } while (0)
156
#define fread_or_die(buf,sz,len,fp) WELLMANNERED_ASSERT (fread ((buf), (sz), (len), (fp)) == (len), "fread() failed with errno %d (%s)", errno, strerror (errno))
109
#define fwrite_or_die(buf,sz,len,fp) do { if ((fwrite ((buf), (sz), (len), (fp)) != (len)) || (fflush ((fp)) != 0)) { fprintf (stderr, "ifstool: fatal error: fwrite() failure within %s() in %s line %d: errno %d (%s)\n", __FUNCTION__, __FILENAME__, __LINE__, errno, strerror (errno)); exit (1); } } while (0)
157
#define fwrite_or_die(buf,sz,len,fp) WELLMANNERED_ASSERT ((fwrite ((buf), (sz), (len), (fp)) == (len)) && (fflush ((fp)) == 0), "flushed fwrite() failed with errno %d (%s)", errno, strerror (errno))
110
 
158
 
111
 
-
 
112
#define ROUND_TO_UPPER_MULTIPLE(val,multiple) ((((val) + (size_t) (multiple) - 1) / (multiple)) * (multiple)) // note that val is being evaluated once, so it can be the result of a function call
-
 
113
#ifdef _WIN32
-
 
114
#define IS_DIRSEP(c) (((c) == '/') || ((c) == '\\'))
-
 
115
#define PATH_SEP ';'
-
 
116
#define PATH_SEP_STR ";"
-
 
117
#else // !_WIN32, thus POSIX
-
 
118
#define IS_DIRSEP(c) ((c) == '/')
-
 
119
#define PATH_SEP ':'
-
 
120
#define PATH_SEP_STR ":"
-
 
121
#endif // _WIN32
-
 
122
#define RECORD_SEP '\x1e' // ASCII record separator
-
 
123
#define RECORD_SEP_STR "\x1e" // ASCII record separator (as string)
-
 
124
 
159
 
125
// macros for accessing ELF files
160
// macros for accessing ELF files
126
#define ELF_MAGIC_STR "\x7f" "ELF"
161
#define ELF_MAGIC_STR "\x7f" "ELF"
127
#define ELF_ENDIAN_LITTLE 1 // 'endianness' member of an ELF header: ELF file is little endian
162
#define ELF_ENDIAN_LITTLE 1 // 'endianness' member of an ELF header: ELF file is little endian
128
#define ELF_ENDIAN_BIG    2 // 'endianness' member of an ELF header: ELF file is big endian
163
#define ELF_ENDIAN_BIG    2 // 'endianness' member of an ELF header: ELF file is big endian
Line 164... Line 199...
164
#define ELF_GET_STRING(elfhdr,elfstruct,member) ((elfhdr)->u.elf.platform_size == 2 ? (elfstruct)->u.elf64.member : (elfstruct)->u.elf32.member) // this macro supports 32- and 64-bit ELF files transparently
199
#define ELF_GET_STRING(elfhdr,elfstruct,member) ((elfhdr)->u.elf.platform_size == 2 ? (elfstruct)->u.elf64.member : (elfstruct)->u.elf32.member) // this macro supports 32- and 64-bit ELF files transparently
165
#define ELF_SET_STRING(elfhdr,elfstruct,member,data,len) memcpy (((elfhdr)->u.elf.platform_size == 2 ? (elfstruct)->u.elf64.member : (elfstruct)->u.elf32.member), (data), (len)) // this macro supports 32- and 64-bit ELF files transparently
200
#define ELF_SET_STRING(elfhdr,elfstruct,member,data,len) memcpy (((elfhdr)->u.elf.platform_size == 2 ? (elfstruct)->u.elf64.member : (elfstruct)->u.elf32.member), (data), (len)) // this macro supports 32- and 64-bit ELF files transparently
166
#define ELF_STRUCT_SIZE(elfhdr,elfstruct) ((elfhdr)->u.elf.platform_size == 2 ? sizeof ((elfstruct)->u.elf64) : sizeof ((elfstruct)->u.elf32)) // this macro supports 32- and 64-bit ELF files transparently
201
#define ELF_STRUCT_SIZE(elfhdr,elfstruct) ((elfhdr)->u.elf.platform_size == 2 ? sizeof ((elfstruct)->u.elf64) : sizeof ((elfstruct)->u.elf32)) // this macro supports 32- and 64-bit ELF files transparently
167
 
202
 
168
 
203
 
169
 
-
 
-
 
204
// placeholder value
170
#define WILL_BE_FILLED_LATER 0xbaadf00d
205
#define WILL_BE_FILLED_LATER 0xbaadf00d // urgh
171
 
206
 
172
 
207
 
173
// bitmapped flags used in the flags1 member of the startup header
208
// bitmapped flags used in the flags1 member of the startup header
174
#define STARTUP_HDR_FLAGS1_VIRTUAL        (1 << 0)
209
#define STARTUP_HDR_FLAGS1_VIRTUAL        (1 << 0)
175
#define STARTUP_HDR_FLAGS1_BIGENDIAN      (1 << 1)
210
#define STARTUP_HDR_FLAGS1_BIGENDIAN      (1 << 1)
Line 192... Line 227...
192
 
227
 
193
// bitmapped flags superposed to a filesystem entry's inode number
228
// bitmapped flags superposed to a filesystem entry's inode number
194
#define IFS_INO_PROCESSED_ELF 0x80000000
229
#define IFS_INO_PROCESSED_ELF 0x80000000
195
#define IFS_INO_RUNONCE_ELF   0x40000000
230
#define IFS_INO_RUNONCE_ELF   0x40000000
196
#define IFS_INO_BOOTSTRAP_EXE 0x20000000
231
#define IFS_INO_BOOTSTRAP_EXE 0x20000000
-
 
232
 
-
 
233
 
-
 
234
// miscellaneous macros
-
 
235
#define ROUND_TO_UPPER_MULTIPLE(val,multiple) ((((val) + (size_t) (multiple) - 1) / (multiple)) * (multiple)) // note that val is being evaluated once, so it can be the result of a function call
-
 
236
#ifdef _WIN32
-
 
237
#define IS_DIRSEP(c) (((c) == '/') || ((c) == '\\')) // platform-specific directory separator, Win32 variant
-
 
238
#define PATH_SEP ';' // platform-specific PATH element separator, Win32 variant
-
 
239
#define PATH_SEP_STR ";" // platform-specific PATH element separator (as string), Win32 variant
-
 
240
#else // !_WIN32, thus POSIX
-
 
241
#define IS_DIRSEP(c) ((c) == '/') // platform-specific directory separator, UNIX variant
-
 
242
#define PATH_SEP ':' // platform-specific PATH element separator, UNIX variant
-
 
243
#define PATH_SEP_STR ":" // platform-specific PATH element separator (as string), UNIX variant
-
 
244
#endif // _WIN32
-
 
245
#define RECORD_SEP '\x1e' // arbitrarily-chosen ASCII record separator
-
 
246
#define RECORD_SEP_STR "\x1e" // arbitrarily-chosen ASCII record separator (as string)
197
 
247
 
198
 
248
 
199
// SHA-512 block and digest sizes
249
// SHA-512 block and digest sizes
200
#define SHA512_BLOCK_LENGTH 128 // in bytes
250
#define SHA512_BLOCK_LENGTH 128 // in bytes
201
#define SHA512_DIGEST_LENGTH 64 // in bytes
251
#define SHA512_DIGEST_LENGTH 64 // in bytes
Line 206... Line 256...
206
{
256
{
207
   uint64_t state[8];
257
   uint64_t state[8];
208
   uint64_t bitcount[2];
258
   uint64_t bitcount[2];
209
   uint8_t buffer[SHA512_BLOCK_LENGTH];
259
   uint8_t buffer[SHA512_BLOCK_LENGTH];
210
} SHA512_CTX;
260
} SHA512_CTX;
211
 
-
 
212
 
-
 
213
#ifdef _MSC_VER
-
 
214
#pragma pack(push)
-
 
215
#pragma pack(1)
-
 
216
#endif // _MSC_VER
-
 
217
 
261
 
218
 
262
 
219
#if 0 // TODO: startup script compiler. Someday.
263
#if 0 // TODO: startup script compiler. Someday.
220
#define SCRIPT_FLAGS_EXTSCHED   0x01
264
#define SCRIPT_FLAGS_EXTSCHED   0x01
221
#define SCRIPT_FLAGS_SESSION    0x02
265
#define SCRIPT_FLAGS_SESSION    0x02
Line 245... Line 289...
245
#define SCRIPT_APS_SYSTEM_PARTITION_NAME "System"
289
#define SCRIPT_APS_SYSTEM_PARTITION_NAME "System"
246
#define SCRIPT_APS_PARTITION_NAME_LENGTH 15
290
#define SCRIPT_APS_PARTITION_NAME_LENGTH 15
247
#define SCRIPT_APS_MAX_PARTITIONS        8
291
#define SCRIPT_APS_MAX_PARTITIONS        8
248
 
292
 
249
 
293
 
-
 
294
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
250
typedef struct __attribute__((packed)) bootscriptcmd_header_s
295
typedef PACKED (struct) bootscriptcmd_header_s
251
{
296
{
252
   uint16_t size; // size of cmd entry
297
   uint16_t size; // size of cmd entry
253
   uint8_t type;
298
   uint8_t type;
254
   uint8_t spare;
299
   uint8_t spare;
255
} bootscriptcmd_header_t;
300
} bootscriptcmd_header_t;
-
 
301
END_OF_PACKED_STRUCT () // restore default alignment
256
 
302
 
257
 
303
 
-
 
304
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
258
typedef union bootscriptcmd_s
305
typedef union bootscriptcmd_s
259
{
306
{
260
   struct __attribute__((packed)) script_external
307
   PACKED (struct) script_external
261
   {
308
   {
262
      bootscriptcmd_header_t hdr;
309
      bootscriptcmd_header_t hdr;
263
      uint8_t cpu; // CPU (turn into runmask)
310
      uint8_t cpu; // CPU (turn into runmask)
264
      uint8_t flags;
311
      uint8_t flags;
265
      union script_external_extsched
312
      union script_external_extsched
266
      {
313
      {
267
         uint8_t reserved[2];
314
         uint8_t reserved[2];
268
         struct __attribute__((packed))
315
         PACKED (struct)
269
         {
316
         {
270
            uint8_t id;
317
            uint8_t id;
271
            uint8_t reserved[1];
318
            uint8_t reserved[1];
272
         } aps;
319
         } aps;
273
      } extsched; // extended scheduler
320
      } extsched; // extended scheduler
Line 275... Line 322...
275
      uint8_t priority; // priority to run cmd at
322
      uint8_t priority; // priority to run cmd at
276
      uint8_t argc; // # of args
323
      uint8_t argc; // # of args
277
      uint8_t envc; // # of environment entries
324
      uint8_t envc; // # of environment entries
278
      char args[0]; // executable, argv, envp (null padded to 32-bit align)
325
      char args[0]; // executable, argv, envp (null padded to 32-bit align)
279
   } external;
326
   } external;
280
   struct __attribute__((packed)) script_waitfor_reopen
327
   PACKED (struct) script_waitfor_reopen
281
   {
328
   {
282
      bootscriptcmd_header_t hdr;
329
      bootscriptcmd_header_t hdr;
283
      uint16_t checks;
330
      uint16_t checks;
284
      char fname[0]; // char fname[] (null padded to 32-bit align)
331
      char fname[0]; // char fname[] (null padded to 32-bit align)
285
   } waitfor_reopen;
332
   } waitfor_reopen;
286
   struct __attribute__((packed)) script_display_msg
333
   PACKED (struct) script_display_msg
287
   {
334
   {
288
      bootscriptcmd_header_t hdr;
335
      bootscriptcmd_header_t hdr;
289
      char msg[0]; // char msg[] (null padded to 32-bit align)
336
      char msg[0]; // char msg[] (null padded to 32-bit align)
290
   } display_msg;
337
   } display_msg;
291
   struct __attribute__((packed)) script_procmgr_symlink
338
   PACKED (struct) script_procmgr_symlink
292
   {
339
   {
293
      bootscriptcmd_header_t hdr;
340
      bootscriptcmd_header_t hdr;
294
      char src_dest[0]; // <src_name>, '\0', <dest_name> '\0' (null padded to 32-bit align)
341
      char src_dest[0]; // <src_name>, '\0', <dest_name> '\0' (null padded to 32-bit align)
295
   } procmgr_symlink;
342
   } procmgr_symlink;
296
   struct __attribute__((packed)) script_extsched_aps
343
   PACKED (struct) script_extsched_aps
297
   {
344
   {
298
      bootscriptcmd_header_t hdr;
345
      bootscriptcmd_header_t hdr;
299
      uint8_t parent;
346
      uint8_t parent;
300
      uint8_t budget;
347
      uint8_t budget;
301
      uint16_t critical;
348
      uint16_t critical;
302
      uint8_t id;
349
      uint8_t id;
303
      char pname[0]; // char pname[] (null padded to 32-bit align)
350
      char pname[0]; // char pname[] (null padded to 32-bit align)
304
   } extsched_aps;
351
   } extsched_aps;
305
} bootscriptcmd_t;
352
} bootscriptcmd_t;
-
 
353
END_OF_PACKED_STRUCT () // restore default alignment
306
#endif // 0
354
#endif // 0
307
 
355
 
308
 
356
 
309
#define INITIAL_STARTUP_SCRIPT \
357
#define INITIAL_STARTUP_SCRIPT \
310
   /* procmgr_symlink /proc/boot/ldqnx-64.so.2 /usr/lib/ldqnx-64.so.2 */ \
358
   /* procmgr_symlink /proc/boot/ldqnx-64.so.2 /usr/lib/ldqnx-64.so.2 */ \
Line 315... Line 363...
315
   "\x18\x00" /*size*/ "\x03" /*type*/ "\x00" /*spare*/ "Startup complete\n\0" "\x00\00" /*padding*/ \
363
   "\x18\x00" /*size*/ "\x03" /*type*/ "\x00" /*spare*/ "Startup complete\n\0" "\x00\00" /*padding*/ \
316
   /* trailer */ \
364
   /* trailer */ \
317
   "\x00\x00\x00\x00"
365
   "\x00\x00\x00\x00"
318
 
366
 
319
 
367
 
-
 
368
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
320
typedef struct __attribute__((packed)) fsentry_s
369
typedef PACKED (struct) fsentry_s
321
{
370
{
322
   struct __attribute__((packed)) fsentry_header_s
371
   PACKED (struct) fsentry_header_s
323
   {
372
   {
324
      uint16_t size; // size of dirent
373
      uint16_t size; // size of dirent
325
      uint16_t extattr_offset; // if zero, no extattr data
374
      uint16_t extattr_offset; // if zero, no extattr data
326
      uint32_t ino; // if zero, skip entry
375
      uint32_t ino; // if zero, skip entry
327
      uint32_t mode; // mode and perms of entry
376
      uint32_t mode; // mode and perms of entry
328
      uint32_t gid;
377
      uint32_t gid;
329
      uint32_t uid;
378
      uint32_t uid;
330
      uint32_t mtime;
379
      uint32_t mtime;
331
   } header;
380
   } header;
332
   union __attribute__((packed)) fsentry_specific_u
381
   PACKED (union) fsentry_specific_u
333
   {
382
   {
334
      struct __attribute__((packed)) fsentry_file_s // when (mode & S_IFMT) == S_IFREG
383
      PACKED (struct) fsentry_file_s // when (mode & S_IFMT) == S_IFREG
335
      {
384
      {
336
         uint32_t offset; // offset from header
385
         uint32_t offset; // offset from header
337
         uint32_t size;
386
         uint32_t size;
338
         char *path; // null terminated path (no leading slash)
387
         char *path; // null terminated path (no leading slash)
339
         char *UNSAVED_databuf; // file data blob buffer (NOT SAVED IN THE IFS)
388
         char *UNSAVED_databuf; // file data blob buffer (NOT SAVED IN THE IFS)
340
      } file;
389
      } file;
341
      struct __attribute__((packed)) fsentry_dir_s // when (mode & S_IFMT) == S_IFDIR
390
      PACKED (struct) fsentry_dir_s // when (mode & S_IFMT) == S_IFDIR
342
      {
391
      {
343
         char *path; // null terminated path (no leading slash)
392
         char *path; // null terminated path (no leading slash)
344
      } dir;
393
      } dir;
345
      struct __attribute__((packed)) fsentry_symlink_s // when (mode & S_IFMT) == S_IFLNK
394
      PACKED (struct) fsentry_symlink_s // when (mode & S_IFMT) == S_IFLNK
346
      {
395
      {
347
         uint16_t sym_offset; // offset to 'contents' from 'path'
396
         uint16_t sym_offset; // offset to 'contents' from 'path'
348
         uint16_t sym_size; // strlen (contents)
397
         uint16_t sym_size; // strlen (contents)
349
         char *path; // null terminated path (no leading slash)
398
         char *path; // null terminated path (no leading slash)
350
         char *contents; // null terminated symlink contents
399
         char *contents; // null terminated symlink contents
351
      } symlink;
400
      } symlink;
352
      struct __attribute__((packed)) fsentry_device_s // when (mode & S_IFMT) == S_IF<CHR|BLK|FIFO|NAM|SOCK>
401
      PACKED (struct) fsentry_device_s // when (mode & S_IFMT) == S_IF<CHR|BLK|FIFO|NAM|SOCK>
353
      {
402
      {
354
         uint32_t dev;
403
         uint32_t dev;
355
         uint32_t rdev;
404
         uint32_t rdev;
356
         char *path; // null terminated path (no leading slash)
405
         char *path; // null terminated path (no leading slash)
357
      } device;
406
      } device;
358
   } u;
407
   } u;
359
   bool UNSAVED_was_data_written; // whether this entry's data was written to the image (NOT SAVED IN THE IFS)
408
   bool UNSAVED_was_data_written; // whether this entry's data was written to the image (NOT SAVED IN THE IFS)
360
} fsentry_t;
409
} fsentry_t;
-
 
410
END_OF_PACKED_STRUCT () // restore default alignment
361
 
411
 
362
 
412
 
-
 
413
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
363
typedef struct __attribute__((packed)) startup_header_s // size 256 bytes
414
typedef PACKED (struct) startup_header_s // size 256 bytes
364
{
415
{
365
                           // I - used by the QNX IPL
416
   // I - used by the QNX IPL
366
                           // S - used by the startup program
417
   // S - used by the startup program
367
   uint8_t signature[4];   // [I ] Header signature, "\xeb\x7e\xff\x00"
418
   uint8_t signature[4];   // [I ] Header signature, "\xeb\x7e\xff\x00"
368
   uint16_t version;       // [I ] Header version, i.e. 1
419
   uint16_t version;       // [I ] Header version, i.e. 1
369
   uint8_t flags1;         // [IS] Misc flags, 0x21 (= 0x20 | STARTUP_HDR_FLAGS1_VIRTUAL)
420
   uint8_t flags1;         // [IS] Misc flags, 0x21 (= 0x20 | STARTUP_HDR_FLAGS1_VIRTUAL)
370
   uint8_t flags2;         // [  ] No flags defined yet (0)
421
   uint8_t flags2;         // [  ] No flags defined yet (0)
371
   uint16_t header_size;   // [ S] sizeof(struct startup_header), i.e. 256
422
   uint16_t header_size;   // [ S] sizeof(struct startup_header), i.e. 256
Line 383... Line 434...
383
   uint16_t zero0;         // [  ] Zeros
434
   uint16_t zero0;         // [  ] Zeros
384
   uint32_t zero[1];       // [  ] Zeros
435
   uint32_t zero[1];       // [  ] Zeros
385
   uint64_t addr_off;      // [ S] Offset to add to startup_vaddr, image_paddr, ram_paddr, and imagefs_paddr members, here zero (0)
436
   uint64_t addr_off;      // [ S] Offset to add to startup_vaddr, image_paddr, ram_paddr, and imagefs_paddr members, here zero (0)
386
   uint32_t info[48];      // [IS] Array of startup_info* structures (zero filled)
437
   uint32_t info[48];      // [IS] Array of startup_info* structures (zero filled)
387
} startup_header_t;
438
} startup_header_t;
-
 
439
END_OF_PACKED_STRUCT () // restore default alignment
388
 
440
 
389
 
441
 
-
 
442
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
390
typedef struct __attribute__((packed)) startup_trailer_s
443
typedef PACKED (struct) startup_trailer_s
391
{
444
{
392
   uint32_t cksum; // checksum from start of header to start of trailer
445
   uint32_t cksum; // checksum from start of header to start of trailer
393
} startup_trailer_v1_t;
446
} startup_trailer_v1_t;
-
 
447
END_OF_PACKED_STRUCT () // restore default alignment
394
 
448
 
395
 
449
 
396
// NOTE: The checksums in this trailer will only be valid prior to entering startup.
450
// NOTE: The checksums in this trailer will only be valid prior to entering startup.
397
// Because the startup binary is executed in-place, its data segment will change once the program is running.
451
// Because the startup binary is executed in-place, its data segment will change once the program is running.
398
// Hence, any checksum validation would need to be done by the boot loader / IFS.
452
// Hence, any checksum validation would need to be done by the boot loader / IFS.
-
 
453
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
399
typedef struct __attribute__((packed)) startup_trailer_v2_s
454
typedef PACKED (struct) startup_trailer_v2_s
400
{
455
{
401
   uint8_t sha512[64]; // SHA512 from start of header to start of trailer
456
   uint8_t sha512[64]; // SHA512 from start of header to start of trailer
402
   uint32_t cksum; // checksum from start of header to start of this member
457
   uint32_t cksum; // checksum from start of header to start of this member
403
} startup_trailer_v2_t;
458
} startup_trailer_v2_t;
-
 
459
END_OF_PACKED_STRUCT () // restore default alignment
404
 
460
 
405
 
461
 
-
 
462
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
406
typedef struct __attribute__((packed)) image_header_s
463
typedef PACKED (struct) image_header_s
407
{
464
{
408
   uint8_t signature[7]; // image filesystem signature, i.e. "imagefs"
465
   uint8_t signature[7]; // image filesystem signature, i.e. "imagefs"
409
   uint8_t flags; // endian neutral flags, 0x1c
466
   uint8_t flags; // endian neutral flags, 0x1c
410
   uint32_t image_size; // size from start of header to end of trailer (here 0xca6fe0 or 13 266 912)
467
   uint32_t image_size; // size from start of header to end of trailer (here 0xca6fe0 or 13 266 912)
411
   uint32_t hdr_dir_size; // size from start of header to last dirent (here 0x12b8 or 4792)
468
   uint32_t hdr_dir_size; // size from start of header to last dirent (here 0x12b8 or 4792)
Line 415... Line 472...
415
   uint32_t chain_paddr; // offset to next filesystem signature (0)
472
   uint32_t chain_paddr; // offset to next filesystem signature (0)
416
   uint32_t spare[10]; // zerofill
473
   uint32_t spare[10]; // zerofill
417
   uint32_t mountflags; // default _MOUNT_* from sys/iomsg.h (0)
474
   uint32_t mountflags; // default _MOUNT_* from sys/iomsg.h (0)
418
   char mountpoint[4]; // default mountpoint for image ("/" + "\0\0\0")
475
   char mountpoint[4]; // default mountpoint for image ("/" + "\0\0\0")
419
} image_header_t;
476
} image_header_t;
-
 
477
END_OF_PACKED_STRUCT () // restore default alignment
420
 
478
 
421
 
479
 
-
 
480
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
422
typedef struct __attribute__((packed)) image_trailer_v1_s
481
typedef PACKED (struct) image_trailer_v1_s
423
{
482
{
424
   uint32_t cksum; // checksum from start of header to start of trailer
483
   uint32_t cksum; // checksum from start of header to start of trailer
425
} image_trailer_v1_t; // NOTE: this is the same structure as startup_trailer_v1_t
484
} image_trailer_v1_t; // NOTE: this is the same structure as startup_trailer_v1_t
-
 
485
END_OF_PACKED_STRUCT () // restore default alignment
426
 
486
 
427
 
487
 
428
// NOTE: the checksums in this trailer will only be valid until the first non-startup bootstrap binary (e.g., startup-verifier, procnto, ...) is invoked.
488
// NOTE: the checksums in this trailer will only be valid until the first non-startup bootstrap binary (e.g., startup-verifier, procnto, ...) is invoked.
429
// Because bootstrap binaries execute in-place, their data segments will change once the programs are running.
489
// Because bootstrap binaries execute in-place, their data segments will change once the programs are running.
430
// Hence, any checksum validation would need to be done either by the boot loader / IFS or by the startup.
490
// Hence, any checksum validation would need to be done either by the boot loader / IFS or by the startup.
-
 
491
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
431
typedef struct __attribute__((packed)) image_trailer_v2_s
492
typedef PACKED (struct) image_trailer_v2_s
432
{
493
{
433
   uint8_t sha512[64]; // SHA512 from start of image header to start of trailer
494
   uint8_t sha512[64]; // SHA512 from start of image header to start of trailer
434
   uint32_t cksum; // checksum from start of header to start of this member
495
   uint32_t cksum; // checksum from start of header to start of this member
435
} image_trailer_v2_t; // NOTE: this is the same structure as startup_trailer_v2_t
496
} image_trailer_v2_t; // NOTE: this is the same structure as startup_trailer_v2_t
-
 
497
END_OF_PACKED_STRUCT () // restore default alignment
436
 
498
 
437
 
499
 
438
// Executable and Linkable Format master header structure type definition
500
// Executable and Linkable Format master header structure type definition
-
 
501
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
439
typedef struct __attribute__((packed)) elf_header_s
502
typedef PACKED (struct) elf_header_s
440
{
503
{
441
   union __attribute__((packed))
504
   PACKED (union)
442
   {
505
   {
443
      struct __attribute__((packed))
506
      PACKED (struct)
444
      {
507
      {
445
         uint8_t magic[4];                     // offset 0: "\x7f" + "ELF"
508
         uint8_t magic[4];                     // offset 0: "\x7f" + "ELF"
446
         uint8_t platform_size;                // offset 4: 1 = 32-bit, 2 = 64-bit
509
         uint8_t platform_size;                // offset 4: 1 = 32-bit, 2 = 64-bit
447
         uint8_t endianness;                   // offset 5: 1 = little endian, 2 = big endian
510
         uint8_t endianness;                   // offset 5: 1 = little endian, 2 = big endian
448
         uint8_t header_version;               // offset 6: typically 1
511
         uint8_t header_version;               // offset 6: typically 1
Line 450... Line 513...
450
         uint8_t spare[8];                     // offset 8: zeroes
513
         uint8_t spare[8];                     // offset 8: zeroes
451
         uint16_t type;                        // offset 16: 1 = relocatable, 2 = executable, 3 = shared, 4 = core dump
514
         uint16_t type;                        // offset 16: 1 = relocatable, 2 = executable, 3 = shared, 4 = core dump
452
         uint16_t instruction_set;             // offset 18: 2 = Sparc, 3 = i386, 8 = MIPS, 20 = PowerPC, 40 = ARM, 42 = SuperH, 50 = IA-64, 62 = x86_64, 183 = AArch64, 243 = RISC-V
515
         uint16_t instruction_set;             // offset 18: 2 = Sparc, 3 = i386, 8 = MIPS, 20 = PowerPC, 40 = ARM, 42 = SuperH, 50 = IA-64, 62 = x86_64, 183 = AArch64, 243 = RISC-V
453
         uint32_t elf_version;                 // offset 20: typically 1
516
         uint32_t elf_version;                 // offset 20: typically 1
454
      } elf;
517
      } elf;
455
      struct __attribute__((packed)) // size == 52
518
      PACKED (struct) // size == 52
456
      {
519
      {
457
         uint8_t magic[4];                     // offset 0: "\x7f" + "ELF"
520
         uint8_t magic[4];                     // offset 0: "\x7f" + "ELF"
458
         uint8_t platform_size;                // offset 4: 1 = 32-bit, 2 = 64-bit
521
         uint8_t platform_size;                // offset 4: 1 = 32-bit, 2 = 64-bit
459
         uint8_t endianness;                   // offset 5: 1 = little endian, 2 = big endian
522
         uint8_t endianness;                   // offset 5: 1 = little endian, 2 = big endian
460
         uint8_t header_version;               // offset 6: typically 1
523
         uint8_t header_version;               // offset 6: typically 1
Line 472... Line 535...
472
         uint16_t program_header_table_len;    // offset 44: number of entries in the program header table
535
         uint16_t program_header_table_len;    // offset 44: number of entries in the program header table
473
         uint16_t section_header_item_size;    // offset 46: size of an entry in the section header table
536
         uint16_t section_header_item_size;    // offset 46: size of an entry in the section header table
474
         uint16_t section_header_table_len;    // offset 48: number of entries in the section header table
537
         uint16_t section_header_table_len;    // offset 48: number of entries in the section header table
475
         uint16_t section_header_names_idx;    // offset 50: index of the entry in the section header table that contains the section names
538
         uint16_t section_header_names_idx;    // offset 50: index of the entry in the section header table that contains the section names
476
      } elf32; // size == 52
539
      } elf32; // size == 52
477
      struct __attribute__((packed)) // size == 64
540
      PACKED (struct) // size == 64
478
      {
541
      {
479
         uint8_t magic[4];                     // offset 0: "\x7f" + "ELF"
542
         uint8_t magic[4];                     // offset 0: "\x7f" + "ELF"
480
         uint8_t platform_size;                // offset 4: 1 = 32-bit, 2 = 64-bit
543
         uint8_t platform_size;                // offset 4: 1 = 32-bit, 2 = 64-bit
481
         uint8_t endianness;                   // offset 5: 1 = little endian, 2 = big endian
544
         uint8_t endianness;                   // offset 5: 1 = little endian, 2 = big endian
482
         uint8_t header_version;               // offset 6: typically 1
545
         uint8_t header_version;               // offset 6: typically 1
Line 496... Line 559...
496
         uint16_t section_header_table_len;    // offset 60: number of entries in the section header table
559
         uint16_t section_header_table_len;    // offset 60: number of entries in the section header table
497
         uint16_t section_header_names_idx;    // offset 62: index of the entry in the section header table that contains the section names
560
         uint16_t section_header_names_idx;    // offset 62: index of the entry in the section header table that contains the section names
498
      } elf64; // size == 64
561
      } elf64; // size == 64
499
   } u;
562
   } u;
500
} elf_header_t;
563
} elf_header_t;
-
 
564
END_OF_PACKED_STRUCT () // restore default alignment
501
 
565
 
502
 
566
 
503
// Executable and Linkable Format program header structure type definition
567
// Executable and Linkable Format program header structure type definition
-
 
568
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
504
typedef struct __attribute__((packed)) elf_program_header_s
569
typedef PACKED (struct) elf_program_header_s
505
{
570
{
506
   union __attribute__((packed))
571
   PACKED (union)
507
   {
572
   {
508
      struct __attribute__((packed))
573
      PACKED (struct)
509
      {
574
      {
510
         uint32_t segment_type; // offset 0: type of segment (0: unused table entry, 1: loadable, 2: dynamic linking information, 3: interpreter information, 4: auxiliary information, 5: reserved, 6: this very segment, 7: TLS template)
575
         uint32_t segment_type; // offset 0: type of segment (0: unused table entry, 1: loadable, 2: dynamic linking information, 3: interpreter information, 4: auxiliary information, 5: reserved, 6: this very segment, 7: TLS template)
511
      } elf;
576
      } elf;
512
      struct __attribute__((packed)) // size == 32
577
      PACKED (struct) // size == 32
513
      {
578
      {
514
         uint32_t segment_type;   // offset 0: type of segment (0: unused table entry, 1: loadable, 2: dynamic linking information, 3: interpreter information, 4: auxiliary information, 5: reserved, 6: this very segment, 7: TLS template)
579
         uint32_t segment_type;   // offset 0: type of segment (0: unused table entry, 1: loadable, 2: dynamic linking information, 3: interpreter information, 4: auxiliary information, 5: reserved, 6: this very segment, 7: TLS template)
515
         uint32_t file_offset;    // offset 4: file offset of this segment
580
         uint32_t file_offset;    // offset 4: file offset of this segment
516
         uint32_t virtual_addr;   // offset 8: virtual address where this segment should be mapped in memory
581
         uint32_t virtual_addr;   // offset 8: virtual address where this segment should be mapped in memory
517
         uint32_t physical_addr;  // offset 12: on systems where this is relevant, PHYSICAL address where this segment should be mapped in memory
582
         uint32_t physical_addr;  // offset 12: on systems where this is relevant, PHYSICAL address where this segment should be mapped in memory
518
         uint32_t size_in_file;   // offset 16: size of this segment in the ELF file (may be zero)
583
         uint32_t size_in_file;   // offset 16: size of this segment in the ELF file (may be zero)
519
         uint32_t size_in_memory; // offset 20: size of this segment in memory (may be zero)
584
         uint32_t size_in_memory; // offset 20: size of this segment in memory (may be zero)
520
         uint32_t segment_flags;  // offset 24: bitmap of segment flags (1: executable, 2: writable, 4: readable)
585
         uint32_t segment_flags;  // offset 24: bitmap of segment flags (1: executable, 2: writable, 4: readable)
521
         uint32_t alignment;      // offset 28: memory alignment (0 or 1 mean non alignment, else must be a power of 2 where virtual_addr == file_offset % alignment)
586
         uint32_t alignment;      // offset 28: memory alignment (0 or 1 mean non alignment, else must be a power of 2 where virtual_addr == file_offset % alignment)
522
      } elf32; // size == 32
587
      } elf32; // size == 32
523
      struct __attribute__((packed)) // size == 56
588
      PACKED (struct) // size == 56
524
      {
589
      {
525
         uint32_t segment_type;   // offset 0: type of segment (0: unused table entry, 1: loadable, 2: dynamic linking information, 3: interpreter information, 4: auxiliary information, 5: reserved, 6: this very segment, 7: TLS template)
590
         uint32_t segment_type;   // offset 0: type of segment (0: unused table entry, 1: loadable, 2: dynamic linking information, 3: interpreter information, 4: auxiliary information, 5: reserved, 6: this very segment, 7: TLS template)
526
         uint32_t segment_flags;  // offset 4: bitmap of segment flags (1: executable, 2: writable, 4: readable)
591
         uint32_t segment_flags;  // offset 4: bitmap of segment flags (1: executable, 2: writable, 4: readable)
527
         uint64_t file_offset;    // offset 8: file offset of this segment
592
         uint64_t file_offset;    // offset 8: file offset of this segment
528
         uint64_t virtual_addr;   // offset 16: virtual address where this segment should be mapped in memory
593
         uint64_t virtual_addr;   // offset 16: virtual address where this segment should be mapped in memory
Line 531... Line 596...
531
         uint64_t size_in_memory; // offset 40: size of this segment in memory (may be zero)
596
         uint64_t size_in_memory; // offset 40: size of this segment in memory (may be zero)
532
         uint64_t alignment;      // offset 48: memory alignment (0 or 1 mean non alignment, else must be a power of 2 where virtual_addr == file_offset % alignment)
597
         uint64_t alignment;      // offset 48: memory alignment (0 or 1 mean non alignment, else must be a power of 2 where virtual_addr == file_offset % alignment)
533
      } elf64; // size == 56
598
      } elf64; // size == 56
534
   } u;
599
   } u;
535
} elf_program_header_t;
600
} elf_program_header_t;
-
 
601
END_OF_PACKED_STRUCT () // restore default alignment
536
 
602
 
537
 
603
 
538
// Executable and Linkable Format section header structure type definition
604
// Executable and Linkable Format section header structure type definition
-
 
605
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
539
typedef struct __attribute__((packed)) elf_section_header_s
606
typedef PACKED (struct) elf_section_header_s
540
{
607
{
541
   union __attribute__((packed))
608
   PACKED (union)
542
   {
609
   {
-
 
610
      PACKED (struct)
-
 
611
      {
-
 
612
         uint32_t name_offset; // offset 0: offset in the string table of the name of this section
543
      struct __attribute__((packed)) // size == 40
613
         uint32_t type;        // offset 4: section type (0: unused, 1: program data, 2: symbols table, 3: strings table, 4: relocs with addends, 5: symbols hash table, 6: dyld info, 7: notes, 8: BSS, 9: relocs without addends, 11: dyld symbols table, 14: constructors, 15: destructors, 16, preconstructors, 17: group, 18: extended section indices, 19: number of typedefs ...)
-
 
614
      } elf;
-
 
615
      PACKED (struct) // size == 40
544
      {
616
      {
545
         uint32_t name_offset;  // offset 0: offset in the string table of the name of this section
617
         uint32_t name_offset;  // offset 0: offset in the string table of the name of this section
546
         uint32_t type;         // offset 4:
618
         uint32_t type;         // offset 4: section type (0: unused, 1: program data, 2: symbols table, 3: strings table, 4: relocs with addends, 5: symbols hash table, 6: dyld info, 7: notes, 8: BSS, 9: relocs without addends, 11: dyld symbols table, 14: constructors, 15: destructors, 16, preconstructors, 17: group, 18: extended section indices, 19: number of typedefs ...)
547
         uint32_t flags;        // offset 8:
619
         uint32_t flags;        // offset 8: bitmapped flags (1: writable, 2: takes RAM, 4: executable, 8: reserved, 16: mergeable, 32: contains C-strings, 64: sh_info contains SHT index, 128: preserve order, 256: OS-specific, 512: group member, 1024: TLS template ...)
548
         uint32_t virtual_addr; // offset 12: address in virtual memory where this section may be loaded
620
         uint32_t virtual_addr; // offset 12: address in virtual memory where this section may be loaded
549
         uint32_t file_offset;  // offset 16: offset of this section in the ELF file
621
         uint32_t file_offset;  // offset 16: offset of this section in the ELF file
550
         uint32_t size;         // offset 20: size of this section
622
         uint32_t size;         // offset 20: size of this section
551
         uint32_t linked_index; // offset 24: optional section index of an associated section
623
         uint32_t linked_index; // offset 24: optional section index of an associated section
552
         uint32_t info;         // offset 28: optional extra information
624
         uint32_t info;         // offset 28: optional extra information
553
         uint32_t alignment;    // offset 32: required memory alignment (must be a power of 2)
625
         uint32_t alignment;    // offset 32: required memory alignment (must be a power of 2)
554
         uint32_t entry_size;   // offset 36: for table-like sections, size of an element in the table
626
         uint32_t entry_size;   // offset 36: for table-like sections, size of an element in the table
555
      } elf32; // size == 40
627
      } elf32; // size == 40
556
      struct __attribute__((packed)) // size == 64
628
      PACKED (struct) // size == 64
557
      {
629
      {
558
         uint32_t name_offset;  // offset 0: offset in the string table of the name of this section
630
         uint32_t name_offset;  // offset 0: offset in the string table of the name of this section
559
         uint32_t type;         // offset 4:
631
         uint32_t type;         // offset 4: section type (0: unused, 1: program data, 2: symbols table, 3: strings table, 4: relocs with addends, 5: symbols hash table, 6: dyld info, 7: notes, 8: BSS, 9: relocs without addends, 11: dyld symbols table, 14: constructors, 15: destructors, 16, preconstructors, 17: group, 18: extended section indices, 19: number of typedefs ...)
560
         uint64_t flags;        // offset 8:
632
         uint64_t flags;        // offset 8: bitmapped flags (1: writable, 2: takes RAM, 4: executable, 8: reserved, 16: mergeable, 32: contains C-strings, 64: sh_info contains SHT index, 128: preserve order, 256: OS-specific, 512: group member, 1024: TLS template ...)
561
         uint64_t virtual_addr; // offset 16: address in virtual memory where this section may be loaded
633
         uint64_t virtual_addr; // offset 16: address in virtual memory where this section may be loaded
562
         uint64_t file_offset;  // offset 24: offset of this section in the ELF file
634
         uint64_t file_offset;  // offset 24: offset of this section in the ELF file
563
         uint64_t size;         // offset 32: size of this section
635
         uint64_t size;         // offset 32: size of this section
564
         uint32_t linked_index; // offset 40: optional section index of an associated section
636
         uint32_t linked_index; // offset 40: optional section index of an associated section
565
         uint32_t info;         // offset 44: optional extra information
637
         uint32_t info;         // offset 44: optional extra information
566
         uint64_t alignment;    // offset 48: required memory alignment (must be a power of 2)
638
         uint64_t alignment;    // offset 48: required memory alignment (must be a power of 2)
567
         uint64_t entry_size;   // offset 56: for table-like sections, size of an element in the table
639
         uint64_t entry_size;   // offset 56: for table-like sections, size of an element in the table
568
      } elf64; // size == 64
640
      } elf64; // size == 64
569
   } u;
641
   } u;
570
} elf_section_header_t;
642
} elf_section_header_t;
-
 
643
END_OF_PACKED_STRUCT () // restore default alignment
571
 
644
 
572
 
645
 
573
// Executable and Linkable Format dynamic section entry structure type definition
646
// Executable and Linkable Format dynamic section entry structure type definition
-
 
647
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
574
typedef struct __attribute__((packed)) elf_dynamic_section_entry_s
648
typedef PACKED (struct) elf_dynamic_section_entry_s
575
{
649
{
576
   union __attribute__((packed))
650
   PACKED (union)
577
   {
651
   {
578
      struct __attribute__((packed)) // size == 8
652
      PACKED (struct) // size == 8
579
      {
653
      {
580
         int32_t tag; // dynamic entry type (one of ELF_DT_xxx #defines)
654
         int32_t tag; // dynamic entry type (one of ELF_DT_xxx #defines)
581
         union
-
 
582
         {
-
 
583
            uint32_t as_integer; // value as integer
-
 
584
            uint32_t as_pointer; // value as address
655
         uint32_t value; // value (as integer, or as pointed address)
585
         } value;
-
 
586
      } elf32; // size == 8
656
      } elf32; // size == 8
587
      struct __attribute__((packed)) // size == 16
657
      PACKED (struct) // size == 16
588
      {
658
      {
589
         int64_t tag; // dynamic entry type (one of ELF_DT_xxx #defines)
659
         int64_t tag; // dynamic entry type (one of ELF_DT_xxx #defines)
590
         union
-
 
591
         {
-
 
592
            uint64_t as_integer; // value as intege
-
 
593
            uint64_t as_pointer; // value as address
660
         uint64_t value; // value (as integer, or as pointed address)
594
         } value;
-
 
595
      } elf64; // size == 16
661
      } elf64; // size == 16
596
   } u;
662
   } u;
597
} elf_dynamic_section_entry_t;
663
} elf_dynamic_section_entry_t;
-
 
664
END_OF_PACKED_STRUCT () // restore default alignment
598
 
665
 
599
 
666
 
-
 
667
// generic buffer structure type definition
600
#ifdef _MSC_VER
668
typedef struct buffer_s
-
 
669
{
601
#pragma pack(pop)
670
   uint8_t *bytes; // mallocated data
-
 
671
   size_t len; // length of allocated data
602
#endif // _MSC_VER
672
} buffer_t;
603
 
673
 
604
 
674
 
-
 
675
// IFS directory entry insertion parameters structure type definition
605
typedef struct parms_s
676
typedef struct parms_s
606
{
677
{
607
   int dperms; // directory permissions (e.g. 0755)
678
   int dperms; // directory permissions (e.g. 0755)
608
   int perms; // file permissions (e.g. 0644)
679
   int perms; // file permissions (e.g. 0644)
609
   int uid; // owner user ID (e.g. 0 = root)
680
   int uid; // owner user ID (e.g. 0 = root)
Line 616... Line 687...
616
   bool should_autosymlink_dylib; // dynamic libraries should be written under their official SONAME and a named symlink be created pointing at them
687
   bool should_autosymlink_dylib; // dynamic libraries should be written under their official SONAME and a named symlink be created pointing at them
617
   bool is_compiled_bootscript; // entry has [+script] attribute
688
   bool is_compiled_bootscript; // entry has [+script] attribute
618
   int extra_ino_flags; // bitmap of extra inode flags (IFS_INO_xxx)
689
   int extra_ino_flags; // bitmap of extra inode flags (IFS_INO_xxx)
619
   char search[10 * MAXPATHLEN]; // binary search path (the default one will be constructed at startup)
690
   char search[10 * MAXPATHLEN]; // binary search path (the default one will be constructed at startup)
620
 
691
 
621
   uint8_t *data;
692
   buffer_t data;
622
   size_t datalen;
-
 
623
} parms_t;
693
} parms_t;
624
 
694
 
625
 
695
 
626
// global variables
696
// global variables
627
static char line_buffer[4096]; // scrap buffer for the IFS build file parser
697
static char line_buffer[4096]; // scrap buffer for the IFS build file parser
Line 655... Line 725...
655
static int32_t update_checksum (const void *data, const size_t data_len, const bool is_foreign_endianness); // compute an IFS image or startup checksum to store in the trailer
725
static int32_t update_checksum (const void *data, const size_t data_len, const bool is_foreign_endianness); // compute an IFS image or startup checksum to store in the trailer
656
static long long read_integer (const char *str); // reads an integer number for a string that may be specified in either hex, octal or decimal base, and may have an optional unit suffix (k, m, g, t)
726
static long long read_integer (const char *str); // reads an integer number for a string that may be specified in either hex, octal or decimal base, and may have an optional unit suffix (k, m, g, t)
657
static void hex_fprintf (FILE *fp, const uint8_t *data, size_t data_size, int howmany_columns, const char *fmt, ...); // hexdump-style formatted output to a file stream (which may be stdout/stderr)
727
static void hex_fprintf (FILE *fp, const uint8_t *data, size_t data_size, int howmany_columns, const char *fmt, ...); // hexdump-style formatted output to a file stream (which may be stdout/stderr)
658
static char *binary (const uint8_t x, char char_for_zero, char char_for_one); // returns the binary representation of byte 'x' as a string
728
static char *binary (const uint8_t x, char char_for_zero, char char_for_one); // returns the binary representation of byte 'x' as a string
659
static char *describe_uint8 (const uint8_t x, const char *bitwise_stringdescs[8]); // returns the ORed description of byte 'x' according to the description strings for each bit
729
static char *describe_uint8 (const uint8_t x, const char *bitwise_stringdescs[8]); // returns the ORed description of byte 'x' according to the description strings for each bit
660
static char *read_filecontents (const char *pathname, const char *search_path, uint8_t **databuf, size_t *datalen); // locates pathname among MKIFS_PATH, reads it, places its contents in a buffer (caller frees) and returns a pointer to the resolved pathname (static string)
730
static char *read_filecontents (const char *pathname, const char *search_path, buffer_t *outbuf); // locates pathname among MKIFS_PATH, reads it, places its contents in a buffer (caller frees) and returns a pointer to the resolved pathname (static string)
661
static int fwrite_filecontents (const char *pathname, FILE *fp); // dumps the contents of pathname into fp
731
static int fwrite_filecontents (const char *pathname, FILE *fp); // dumps the contents of pathname into fp
662
static int relative_offset_of_in (const char *name, const char *string_table, const size_t table_len); // returns the relative offset of a particular string in a string table
732
static int relative_offset_of_in (const char *name, const buffer_t *stringbuf); // returns the relative offset of a particular string in a string table
663
static elf_section_header_t *elf_get_section_header_by_name (const elf_header_t *elf, const char *section_name); // get a pointer to a named section header in an ELF file
733
static elf_section_header_t *elf_get_section_header_by_name (const elf_header_t *elf, const char *section_name); // get a pointer to a named section header in an ELF file
664
static size_t fwrite_fsentry (const fsentry_t *fsentry, FILE *fp); // writes the given filesystem entry into fp (without its contents)
734
static size_t fwrite_fsentry (const fsentry_t *fsentry, FILE *fp); // writes the given filesystem entry into fp (without its contents)
665
static size_t add_fsentry (fsentry_t **fsentries, size_t *fsentry_count, parms_t *entry_parms, const char *stored_pathname, const char *buildhost_pathname); // stack up a new filesystem entry
735
static size_t add_fsentry (fsentry_t **fsentries, size_t *fsentry_count, parms_t *entry_parms, const char *stored_pathname, const char *buildhost_pathname); // stack up a new filesystem entry
666
static int fsentry_compare_pathnames_cb (const void *a, const void *b); // qsort() comparison callback that sorts filesystem entries by pathnames
736
static int fsentry_compare_pathnames_cb (const void *a, const void *b); // qsort() comparison callback that sorts filesystem entries by pathnames
667
static void update_MKIFS_PATH (const char *processor);
737
static void update_MKIFS_PATH (const char *processor);
Line 1020... Line 1090...
1020
      }
1090
      }
1021
   return (outstr);
1091
   return (outstr);
1022
}
1092
}
1023
 
1093
 
1024
 
1094
 
1025
static char *read_filecontents (const char *pathname, const char *search_path, uint8_t **databuf, size_t *datalen)
1095
static char *read_filecontents (const char *pathname, const char *search_path, buffer_t *outbuf)
1026
{
1096
{
1027
   // locates pathname among MKIFS_PATH, and places its contents in a buffer (caller frees). Returns resolved pathname (static buffer) or NULL.
1097
   // locates pathname among MKIFS_PATH, and places its contents in a buffer (caller frees). Returns resolved pathname (static buffer) or NULL.
1028
 
1098
 
1029
   static thread_local char final_pathname[MAXPATHLEN];
1099
   static thread_local char final_pathname[MAXPATHLEN];
1030
 
1100
 
Line 1062... Line 1132...
1062
   fp = fopen (final_pathname, "rb");
1132
   fp = fopen (final_pathname, "rb");
1063
   if (fp == NULL)
1133
   if (fp == NULL)
1064
      return (NULL); // unexistent file (errno is set to ENOENT)
1134
      return (NULL); // unexistent file (errno is set to ENOENT)
1065
 
1135
 
1066
   fseek (fp, 0, SEEK_END);
1136
   fseek (fp, 0, SEEK_END);
1067
   *datalen = ftell (fp); // measure file length
1137
   outbuf->len = ftell (fp); // measure file length
1068
   fseek (fp, 0, SEEK_SET);
1138
   fseek (fp, 0, SEEK_SET);
1069
   *databuf = malloc (*datalen);
1139
   outbuf->bytes = malloc (outbuf->len);
1070
   if (*databuf == NULL)
1140
   if (outbuf->bytes == NULL)
1071
   {
1141
   {
1072
      fclose (fp);
1142
      fclose (fp);
1073
      *datalen = 0;
1143
      outbuf->len = 0;
1074
      return (NULL); // out of memory (errno is set to ENOMEM)
1144
      return (NULL); // out of memory (errno is set to ENOMEM)
1075
   }
1145
   }
1076
   if (fread (*databuf, 1, *datalen, fp) != *datalen) // read the file in whole
1146
   if (fread (outbuf->bytes, 1, outbuf->len, fp) != outbuf->len) // read the file in whole
1077
   {
1147
   {
1078
      fclose (fp);
1148
      fclose (fp);
1079
      *datalen = 0;
1149
      outbuf->len = 0;
1080
      return (NULL); // short read (errno is set)
1150
      return (NULL); // short read (errno is set)
1081
   }
1151
   }
1082
   fclose (fp); // close the file
1152
   fclose (fp); // close the file
1083
 
1153
 
1084
   return (final_pathname); // file was read successfully and its content put in databuf with size datalen
1154
   return (final_pathname); // file was read successfully and its content put in databuf with size datalen
Line 1115... Line 1185...
1115
   free (blob_buffer);
1185
   free (blob_buffer);
1116
   return (ret);
1186
   return (ret);
1117
}
1187
}
1118
 
1188
 
1119
 
1189
 
1120
static int relative_offset_of_in (const char *name, const char *string_table, const size_t table_len)
1190
static int relative_offset_of_in (const char *name, const buffer_t *stringbuf)
1121
{
1191
{
1122
   int name_len = (int) strlen (name) + 1;
1192
   int name_len = (int) strlen (name) + 1;
1123
   WELLMANNERED_ASSERT (name_len < table_len, "bad call (name longer than string table)");
1193
   WELLMANNERED_ASSERT (name_len < stringbuf->len, "bad call (name longer than string table)");
1124
   for (int idx = 0; idx <= table_len - name_len; idx++)
1194
   for (int idx = 0; idx <= stringbuf->len - name_len; idx++)
1125
      if (memcmp (&string_table[idx], name, name_len) == 0)
1195
      if (memcmp (&stringbuf->bytes[idx], name, name_len) == 0)
1126
         return (idx);
1196
         return (idx);
1127
   WELLMANNERED_ASSERT (false, "bad call (name '%s' not found in string table)", name);
1197
   WELLMANNERED_ASSERT (false, "bad call (name '%s' not found in string table)", name);
1128
   return (0);
1198
   return (0);
1129
}
1199
}
1130
 
1200
 
Line 1236... Line 1306...
1236
}
1306
}
1237
 
1307
 
1238
 
1308
 
1239
static size_t add_fsentry (fsentry_t **fsentries, size_t *fsentry_count, parms_t *entry_parms, const char *stored_pathname, const char *buildhost_pathname)
1309
static size_t add_fsentry (fsentry_t **fsentries, size_t *fsentry_count, parms_t *entry_parms, const char *stored_pathname, const char *buildhost_pathname)
1240
{
1310
{
1241
   #define ADD_NAME_TO_STRINGTABLE(name,pstrtab,pstrtablen) do { \
1311
   #define ADD_NAME_TO_STRINGTABLE(name,strtab) do { \
1242
      name_len = strlen ((name)) + 1; \
1312
      name_len = strlen ((name)) + 1; \
1243
      reallocated_ptr = realloc (*(pstrtab), *(pstrtablen) + name_len); \
1313
      reallocated_ptr = realloc ((strtab).bytes, (strtab).len + name_len); \
1244
      WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); \
1314
      WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); \
1245
      *(pstrtab) = reallocated_ptr; \
1315
      (strtab).bytes = reallocated_ptr; \
1246
      memcpy (&(*pstrtab)[*(pstrtablen)], (name), name_len); \
1316
      memcpy (&(strtab).bytes[(strtab).len], (name), name_len); \
1247
      *(pstrtablen) += name_len; \
1317
      (strtab).len += name_len; \
-
 
1318
   } while (0)
-
 
1319
   #define APPEND_SECTION_DATA(section,sectionhdr_offset) do { \
-
 
1320
      memcpy (&entry_parms->data.bytes[entry_parms->data.len], (section).bytes, (section).len); /* write section in place */ \
-
 
1321
      free ((section).bytes); /* free it */ \
-
 
1322
      new_shdr = (elf_section_header_t *) &new_shtab.bytes[(sectionhdr_offset)]; /* now fix this section header */ \
-
 
1323
      ELF_SET_NUMERIC (elf, new_shdr, file_offset, entry_parms->data.len); /* fix section offset in the new section headers table */ \
-
 
1324
      entry_parms->data.len += (section).len; /* update new ELF file length */ \
1248
   } while (0)
1325
   } while (0)
1249
 
1326
 
1250
   static thread_local char candidate_pathname[1024];
1327
   static thread_local char candidate_pathname[1024];
1251
   static int inode_count = 0; // will be preincremented each time this function is called
1328
   static int inode_count = 0; // will be preincremented each time this function is called
1252
 
1329
 
Line 1264... Line 1341...
1264
   elf_program_header_t *phdr;
1341
   elf_program_header_t *phdr;
1265
   const char *canonical_dylib_name;
1342
   const char *canonical_dylib_name;
1266
   const char *dynamic_strings; // strings table of the ".dynamic" section
1343
   const char *dynamic_strings; // strings table of the ".dynamic" section
1267
   const char *last_dirsep;
1344
   const char *last_dirsep;
1268
   elf_header_t *elf;
1345
   elf_header_t *elf;
1269
   uint8_t *new_shdr_table = NULL; // mallocated
-
 
1270
   size_t new_shdr_tablesize = 0;
1346
   buffer_t new_shtab = { NULL, 0 };
1271
   uint8_t *elfsection_qnxinfo_data = NULL; // mallocated
-
 
1272
   size_t elfsection_qnxinfo_size = 0;
1347
   buffer_t elfsection_qnxinfo   = { NULL, 0 };
1273
   uint8_t *elfsection_qnxusage_data = NULL; // mallocated
-
 
1274
   size_t elfsection_qnxusage_size = 0;
1348
   buffer_t elfsection_qnxusage  = { NULL, 0 };
1275
   uint8_t *elfsection_debuglink_data = NULL; // mallocated
-
 
1276
   size_t elfsection_debuglink_size = 0;
1349
   buffer_t elfsection_debuglink = { NULL, 0 };
1277
   uint8_t *elfsection_buildid_data = NULL; // mallocated
-
 
1278
   size_t elfsection_buildid_size = 0;
1350
   buffer_t elfsection_buildid   = { NULL, 0 };
1279
   uint8_t *elfsection_shstrtab_data = NULL; // mallocated
-
 
1280
   size_t elfsection_shstrtab_size = 0;
1351
   buffer_t elfsection_shstrtab  = { NULL, 0 };
1281
   char *resolved_pathname;
1352
   char *resolved_pathname;
1282
   void *reallocated_ptr;
1353
   void *reallocated_ptr;
1283
   void *old_data;
1354
   void *old_data;
1284
   struct stat stat_buf;
1355
   struct stat stat_buf;
1285
   size_t new_shdrtable_offset;
1356
   size_t new_shdrtable_offset;
Line 1307... Line 1378...
1307
      }
1378
      }
1308
      else if (entry_parms->is_compiled_bootscript) // else is it a startup script ?
1379
      else if (entry_parms->is_compiled_bootscript) // else is it a startup script ?
1309
         image_bootscript_ino = inode_count + 1; // save boot script inode number for image header
1380
         image_bootscript_ino = inode_count + 1; // save boot script inode number for image header
1310
 
1381
 
1311
      // do we already know the data for this data blob ?
1382
      // do we already know the data for this data blob ?
1312
      if (entry_parms->data != NULL)
1383
      if (entry_parms->data.bytes != NULL)
1313
      {
1384
      {
1314
         entry_parms->mtime = entry_parms->mtime_for_inline_files;
1385
         entry_parms->mtime = entry_parms->mtime_for_inline_files;
1315
         fprintf (stderr, "file: ino 0x%x uid %d gid %d mode 0%o path \"%s\" blob (len %zd)\n", entry_parms->extra_ino_flags | (inode_count + 1), entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->datalen);
1386
         fprintf (stderr, "file: ino 0x%x uid %d gid %d mode 0%o path \"%s\" blob (len %zd)\n", entry_parms->extra_ino_flags | (inode_count + 1), entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data.len);
1316
      }
1387
      }
1317
      else if (buildhost_pathname != NULL) // else was a source file pathname supplied ?
1388
      else if (buildhost_pathname != NULL) // else was a source file pathname supplied ?
1318
      {
1389
      {
1319
         resolved_pathname = read_filecontents (buildhost_pathname, (entry_parms->search[0] != 0 ? entry_parms->search : MKIFS_PATH), &entry_parms->data, &entry_parms->datalen); // locate the file
1390
         resolved_pathname = read_filecontents (buildhost_pathname, (entry_parms->search[0] != 0 ? entry_parms->search : MKIFS_PATH), &entry_parms->data); // locate the file
1320
         if (resolved_pathname == NULL)
1391
         if (resolved_pathname == NULL)
1321
         {
1392
         {
1322
            fprintf (stderr, "fatal error: filesystem entry \"%s\" specified in \"%s\" line %d not found on build host: %s\n", buildhost_pathname, buildfile_pathname, lineno, strerror (errno));
1393
            fprintf (stderr, "fatal error: filesystem entry \"%s\" specified in \"%s\" line %d not found on build host: %s\n", buildhost_pathname, buildfile_pathname, lineno, strerror (errno));
1323
            exit (1);
1394
            exit (1);
1324
         }
1395
         }
1325
         stat (resolved_pathname, &stat_buf); // can't fail
1396
         stat (resolved_pathname, &stat_buf); // can't fail
1326
         if (entry_parms->mtime == UINT32_MAX)
1397
         if (entry_parms->mtime == UINT32_MAX)
1327
            entry_parms->mtime = (uint32_t) stat_buf.st_mtime;
1398
            entry_parms->mtime = (uint32_t) stat_buf.st_mtime;
1328
         fprintf (stderr, "file: ino 0x%x uid %d gid %d mode 0%o path \"%s\" buildhost_file \"%s\" (len %zd)\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, buildhost_pathname, entry_parms->datalen);
1399
         fprintf (stderr, "file: ino 0x%x uid %d gid %d mode 0%o path \"%s\" buildhost_file \"%s\" (len %zd)\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, buildhost_pathname, entry_parms->data.len);
1329
      }
1400
      }
1330
 
1401
 
1331
      // is the file we're storing an ELF file ?
1402
      // is the file we're storing an ELF file ?
1332
      if ((entry_parms->datalen > 52) // file is big enough to contain an ELF header
1403
      if ((entry_parms->data.len > 52) // file is big enough to contain an ELF header
1333
          && ((elf = (elf_header_t *) entry_parms->data) != NULL) // cast (necessary true)
1404
          && ((elf = (elf_header_t *) entry_parms->data.bytes) != NULL) // cast (necessary true)
1334
          && (memcmp (ELF_GET_STRING (elf, elf, magic), ELF_MAGIC_STR, 4) == 0)) // file starts with the ELF magic
1405
          && (memcmp (ELF_GET_STRING (elf, elf, magic), ELF_MAGIC_STR, 4) == 0)) // file starts with the ELF magic
1335
      {
1406
      {
1336
         // is the file we're storing a relocatable executable (i.e. a dynamic library) and should we check for its canonical name ?
1407
         // is the file we're storing a relocatable executable (i.e. a dynamic library) and should we check for its canonical name ?
1337
         if ((ELF_GET_NUMERIC (elf, elf, type) == 3) && entry_parms->should_autosymlink_dylib)
1408
         if ((ELF_GET_NUMERIC (elf, elf, type) == 3) && entry_parms->should_autosymlink_dylib)
1338
         {
1409
         {
Line 1344... Line 1415...
1344
            shdr_dynstr = elf_get_section_header_by_name (elf, ".dynstr");
1415
            shdr_dynstr = elf_get_section_header_by_name (elf, ".dynstr");
1345
 
1416
 
1346
            // make sure we have both the dynamic section header and its own strings table header
1417
            // make sure we have both the dynamic section header and its own strings table header
1347
            if ((shdr_dynamic != NULL) && (shdr_dynstr != NULL))
1418
            if ((shdr_dynamic != NULL) && (shdr_dynstr != NULL))
1348
            {
1419
            {
1349
               dynamic_strings = (char *) &entry_parms->data[ELF_GET_NUMERIC (elf, shdr_dynstr, file_offset)]; // quick access to dynamic sections strings table
1420
               dynamic_strings = (char *) &entry_parms->data.bytes[ELF_GET_NUMERIC (elf, shdr_dynstr, file_offset)]; // quick access to dynamic sections strings table
1350
 
1421
 
1351
               // walk through the dynamic section, look for the DT_SONAME entry
1422
               // walk through the dynamic section, look for the DT_SONAME entry
1352
               for (dynamic_entry = (elf_dynamic_section_entry_t *) &entry_parms->data[ELF_GET_NUMERIC (elf, shdr_dynamic, file_offset)];
1423
               for (dynamic_entry = (elf_dynamic_section_entry_t *) &entry_parms->data.bytes[ELF_GET_NUMERIC (elf, shdr_dynamic, file_offset)];
1353
                    (ELF_GET_NUMERIC (elf, dynamic_entry, tag) != ELF_DT_NULL);
1424
                    (ELF_GET_NUMERIC (elf, dynamic_entry, tag) != ELF_DT_NULL);
1354
                    dynamic_entry = (elf_dynamic_section_entry_t *) ((uint8_t *) dynamic_entry + ELF_STRUCT_SIZE (elf, dynamic_entry)))
1425
                    dynamic_entry = (elf_dynamic_section_entry_t *) ((uint8_t *) dynamic_entry + ELF_STRUCT_SIZE (elf, dynamic_entry)))
1355
                  if (ELF_GET_NUMERIC (elf, dynamic_entry, tag) == ELF_DT_SONAME)
1426
                  if (ELF_GET_NUMERIC (elf, dynamic_entry, tag) == ELF_DT_SONAME)
1356
                  {
1427
                  {
1357
                     canonical_dylib_name = dynamic_strings + ELF_GET_NUMERIC (elf, dynamic_entry, value.as_integer);
1428
                     canonical_dylib_name = dynamic_strings + ELF_GET_NUMERIC (elf, dynamic_entry, value);
1358
                     break;
1429
                     break;
1359
                  }
1430
                  }
1360
 
1431
 
1361
               // do we have it ?
1432
               // do we have it ?
1362
               if ((canonical_dylib_name != NULL) && (canonical_dylib_name[0] != 0))
1433
               if ((canonical_dylib_name != NULL) && (canonical_dylib_name[0] != 0))
Line 1375... Line 1446...
1375
         if (!(entry_parms->extra_ino_flags & IFS_INO_PROCESSED_ELF))
1446
         if (!(entry_parms->extra_ino_flags & IFS_INO_PROCESSED_ELF))
1376
         {
1447
         {
1377
            // NOTE: for each ELF file, mkifs
1448
            // NOTE: for each ELF file, mkifs
1378
            // -> alters the program header table and offsets each p_addr (physical address) member by 0x1400000 plus the current file offset (this cannot be done right now, will need to be done once they are known)
1449
            // -> alters the program header table and offsets each p_addr (physical address) member by 0x1400000 plus the current file offset (this cannot be done right now, will need to be done once they are known)
1379
            // -> throws away and reconstructs the sections table by keeping only the sections that are in the program header, and writes the section table at the start of the first thrown-away section
1450
            // -> throws away and reconstructs the sections table by keeping only the sections that are in the program header, and writes the section table at the start of the first thrown-away section
1380
            // FIXME: what if a section thrown away is located between two program segments ? are they collapsed, moving everything one slot down ? this looks improbable...
1451
            // FIXME: what if a thrown away section is located between two program segments ? are they collapsed, moving the segments beyond it one slot down ?
1381
 
1452
 
1382
            // reconstructed ELF:
1453
            // reconstructed ELF:
1383
            // ==== START OF FILE ====
1454
            // ==== START OF FILE ====
1384
            // ELF header
1455
            // ELF header
1385
            // program header table
1456
            // program header table
1386
            //  (same sections, just p_addr offset down by first section's p_addr)
1457
            //  (same sections, just p_addr offset changed)
1387
            // section data 5 (named ".note.gnu.build-id")
1458
            // section data 5 (named ".note.gnu.build-id")
1388
            //  "............GNU....ZY.....c.o..l"
1459
            //  "............GNU....ZY.....c.o..l"
1389
            // PROGRAM
1460
            // PROGRAM
1390
            // sections table
1461
            // sections table
1391
            // + section 1: ALL ZEROES
1462
            // + section 1: ALL ZEROES
Line 1407... Line 1478...
1407
            //  ".gnu_debuglink\0"
1478
            //  ".gnu_debuglink\0"
1408
            //  "QNX_usage\0"
1479
            //  "QNX_usage\0"
1409
            //  ".note.gnu.build-id\0"
1480
            //  ".note.gnu.build-id\0"
1410
            // ==== END OF FILE ====
1481
            // ==== END OF FILE ====
1411
 
1482
 
1412
            // task 1: alter the program header table, and measure the farthest offset known by this table where we'll write the reconstructed section headers table
1483
            // parse the program header table, and measure the farthest offset known by this table where we'll write the reconstructed section headers table
1413
 
1484
 
1414
            //first_offset = SIZE_MAX;
-
 
1415
            new_shdrtable_offset = 0;
1485
            new_shdrtable_offset = 0;
1416
            table_count = ELF_GET_NUMERIC (elf, elf, program_header_table_len);
1486
            table_count = ELF_GET_NUMERIC (elf, elf, program_header_table_len);
1417
            for (table_index = 0; table_index < table_count; table_index++)
1487
            for (table_index = 0; table_index < table_count; table_index++)
1418
            {
1488
            {
1419
               phdr = (elf_program_header_t *) &entry_parms->data[ELF_GET_NUMERIC (elf, elf, program_header_table_offset) + (size_t) ELF_GET_NUMERIC (elf, elf, program_header_item_size) * table_index]; // quick access to program header
1489
               phdr = (elf_program_header_t *) &entry_parms->data.bytes[ELF_GET_NUMERIC (elf, elf, program_header_table_offset) + (size_t) ELF_GET_NUMERIC (elf, elf, program_header_item_size) * table_index]; // quick access to program header
1420
               //if (first_offset == SIZE_MAX)
-
 
1421
               //   first_offset = ELF_GET_NUMERIC (elf, phdr, physical_addr);
-
 
1422
               if (ELF_GET_NUMERIC (elf, phdr, file_offset) + ELF_GET_NUMERIC (elf, phdr, size_in_file) > new_shdrtable_offset)
1490
               if (ELF_GET_NUMERIC (elf, phdr, file_offset) + ELF_GET_NUMERIC (elf, phdr, size_in_file) > new_shdrtable_offset)
1423
                  new_shdrtable_offset = ELF_GET_NUMERIC (elf, phdr, file_offset) + ELF_GET_NUMERIC (elf, phdr, size_in_file);
1491
                  new_shdrtable_offset = ELF_GET_NUMERIC (elf, phdr, file_offset) + ELF_GET_NUMERIC (elf, phdr, size_in_file);
1424
//               ELF_SET_NUMERIC (elf, phdr, physical_addr, ELF_GET_NUMERIC (elf, phdr, physical_addr) + (0x1400000 + ));
-
 
1425
            }
1492
            }
1426
 
1493
 
1427
            // task 2: re-create the section header table
1494
            // re-create the section header table
1428
 
1495
 
1429
            elfsection_shstrtab_data = malloc (1); // initialize an empty section headers strings table
1496
            elfsection_shstrtab.bytes = malloc (1); // initialize an empty section headers strings table
1430
            WELLMANNERED_ASSERT (elfsection_shstrtab_data, "out of memory");
1497
            WELLMANNERED_ASSERT (elfsection_shstrtab.bytes, "out of memory");
1431
            elfsection_shstrtab_data[0] = 0;
1498
            elfsection_shstrtab.bytes[0] = 0;
1432
            elfsection_shstrtab_size = 1;
1499
            elfsection_shstrtab.len = 1;
1433
            ADD_NAME_TO_STRINGTABLE (".shstrtab", &elfsection_shstrtab_data, &elfsection_shstrtab_size);
1500
            ADD_NAME_TO_STRINGTABLE (".shstrtab", elfsection_shstrtab);
1434
 
1501
 
1435
            reallocated_ptr = realloc (new_shdr_table, new_shdr_tablesize + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more
1502
            new_shtab.bytes = malloc (ELF_STRUCT_SIZE (elf, shdr)); // prepare a section headers table with just the default entry
1436
            WELLMANNERED_ASSERT (reallocated_ptr, "out of memory");
1503
            WELLMANNERED_ASSERT (new_shtab.bytes, "out of memory");
1437
            new_shdr_table = reallocated_ptr; // reallocation succeeded, save the new pointer
-
 
1438
            memset (&new_shdr_table[new_shdr_tablesize], 0, ELF_STRUCT_SIZE (elf, shdr)); // the first section header is always zerofilled
1504
            memset (new_shtab.bytes, 0, ELF_STRUCT_SIZE (elf, shdr)); // the first section header is always zerofilled
1439
            new_shdr_tablesize += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now
1505
            new_shtab.len = ELF_STRUCT_SIZE (elf, shdr); // and remember how big the section headers table is now
1440
            if ((shdr = elf_get_section_header_by_name (elf, "QNX_info")) != NULL)
1506
            if ((shdr = elf_get_section_header_by_name (elf, "QNX_info")) != NULL)
1441
            {
1507
            {
1442
               if (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset) // if this section needs to be moved around, have a copy of it
1508
               if (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset) // if this section needs to be moved around, have a copy of it
1443
               {
1509
               {
1444
                  elfsection_qnxinfo_size = ELF_GET_NUMERIC (elf, shdr, size);
1510
                  elfsection_qnxinfo.len = ELF_GET_NUMERIC (elf, shdr, size);
1445
                  elfsection_qnxinfo_data = malloc (elfsection_qnxinfo_size);
1511
                  elfsection_qnxinfo.bytes = malloc (elfsection_qnxinfo.len);
1446
                  WELLMANNERED_ASSERT (elfsection_qnxinfo_data, "out of memory");
1512
                  WELLMANNERED_ASSERT (elfsection_qnxinfo.bytes, "out of memory");
1447
                  memcpy (elfsection_qnxinfo_data, &entry_parms->data[ELF_GET_NUMERIC (elf, shdr, file_offset)], elfsection_qnxinfo_size);
1513
                  memcpy (elfsection_qnxinfo.bytes, &entry_parms->data.bytes[ELF_GET_NUMERIC (elf, shdr, file_offset)], elfsection_qnxinfo.len);
1448
               }
1514
               }
1449
               reallocated_ptr = realloc (new_shdr_table, new_shdr_tablesize + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more
1515
               reallocated_ptr = realloc (new_shtab.bytes, new_shtab.len + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more
1450
               WELLMANNERED_ASSERT (reallocated_ptr, "out of memory");
1516
               WELLMANNERED_ASSERT (reallocated_ptr, "out of memory");
1451
               new_shdr_table = reallocated_ptr; // reallocation succeeded, save the new pointer
1517
               new_shtab.bytes = reallocated_ptr; // reallocation succeeded, save the new pointer
1452
               new_qnxinfo_shdr_offset = new_shdr_tablesize; // remember the new offset of this section header
1518
               new_qnxinfo_shdr_offset = new_shtab.len; // remember the new offset of this section header
1453
               new_shdr_tablesize += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now
1519
               new_shtab.len += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now
1454
 
1520
 
1455
               new_shdr = (elf_section_header_t *) &new_shdr_table[new_qnxinfo_shdr_offset]; // now populate this section header
1521
               new_shdr = (elf_section_header_t *) &new_shtab.bytes[new_qnxinfo_shdr_offset]; // now populate this section header
1456
               ADD_NAME_TO_STRINGTABLE ("QNX_info", &elfsection_shstrtab_data, &elfsection_shstrtab_size);
1522
               ADD_NAME_TO_STRINGTABLE ("QNX_info", elfsection_shstrtab);
1457
               ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in ("QNX_info", elfsection_shstrtab_data, elfsection_shstrtab_size)); // update the relative offset of the section name
1523
               ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in ("QNX_info", &elfsection_shstrtab)); // update the relative offset of the section name
1458
               ELF_SET_NUMERIC (elf, new_shdr, type,         ELF_GET_NUMERIC (elf, shdr, type)); // duplicate section type
1524
               ELF_SET_NUMERIC (elf, new_shdr, type,         ELF_GET_NUMERIC (elf, shdr, type)); // duplicate section type
1459
               ELF_SET_NUMERIC (elf, new_shdr, flags,        ELF_GET_NUMERIC (elf, shdr, flags)); // duplicate section flags
1525
               ELF_SET_NUMERIC (elf, new_shdr, flags,        ELF_GET_NUMERIC (elf, shdr, flags)); // duplicate section flags
1460
               ELF_SET_NUMERIC (elf, new_shdr, virtual_addr, ELF_GET_NUMERIC (elf, shdr, virtual_addr)); // duplicate section virtual address
1526
               ELF_SET_NUMERIC (elf, new_shdr, virtual_addr, ELF_GET_NUMERIC (elf, shdr, virtual_addr)); // duplicate section virtual address
1461
               ELF_SET_NUMERIC (elf, new_shdr, file_offset, (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset ? WILL_BE_FILLED_LATER : ELF_GET_NUMERIC (elf, shdr, file_offset))); // duplicate section offset only if it doesn't move
1527
               ELF_SET_NUMERIC (elf, new_shdr, file_offset, (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset ? WILL_BE_FILLED_LATER : ELF_GET_NUMERIC (elf, shdr, file_offset))); // duplicate section offset only if it doesn't move
1462
               ELF_SET_NUMERIC (elf, new_shdr, size,         ELF_GET_NUMERIC (elf, shdr, size)); // duplicate section size
1528
               ELF_SET_NUMERIC (elf, new_shdr, size,         ELF_GET_NUMERIC (elf, shdr, size)); // duplicate section size
Line 1467... Line 1533...
1467
            }
1533
            }
1468
            if ((shdr = elf_get_section_header_by_name (elf, ".gnu_debuglink")) != NULL)
1534
            if ((shdr = elf_get_section_header_by_name (elf, ".gnu_debuglink")) != NULL)
1469
            {
1535
            {
1470
               if (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset) // if this section needs to be moved around, have a copy of it
1536
               if (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset) // if this section needs to be moved around, have a copy of it
1471
               {
1537
               {
1472
                  elfsection_debuglink_size = ELF_GET_NUMERIC (elf, shdr, size);
1538
                  elfsection_debuglink.len = ELF_GET_NUMERIC (elf, shdr, size);
1473
                  elfsection_debuglink_data = malloc (elfsection_debuglink_size);
1539
                  elfsection_debuglink.bytes = malloc (elfsection_debuglink.len);
1474
                  WELLMANNERED_ASSERT (elfsection_debuglink_data, "out of memory");
1540
                  WELLMANNERED_ASSERT (elfsection_debuglink.bytes, "out of memory");
1475
                  memcpy (elfsection_debuglink_data, &entry_parms->data[ELF_GET_NUMERIC (elf, shdr, file_offset)], elfsection_debuglink_size);
1541
                  memcpy (elfsection_debuglink.bytes, &entry_parms->data.bytes[ELF_GET_NUMERIC (elf, shdr, file_offset)], elfsection_debuglink.len);
1476
               }
1542
               }
1477
               reallocated_ptr = realloc (new_shdr_table, new_shdr_tablesize + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more
1543
               reallocated_ptr = realloc (new_shtab.bytes, new_shtab.len + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more
1478
               WELLMANNERED_ASSERT (reallocated_ptr, "out of memory");
1544
               WELLMANNERED_ASSERT (reallocated_ptr, "out of memory");
1479
               new_shdr_table = reallocated_ptr; // reallocation succeeded, save the new pointer
1545
               new_shtab.bytes = reallocated_ptr; // reallocation succeeded, save the new pointer
1480
               new_debuglink_shdr_offset = new_shdr_tablesize; // remember the new offset of this section header
1546
               new_debuglink_shdr_offset = new_shtab.len; // remember the new offset of this section header
1481
               new_shdr_tablesize += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now
1547
               new_shtab.len += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now
1482
 
1548
 
1483
               new_shdr = (elf_section_header_t *) &new_shdr_table[new_debuglink_shdr_offset]; // now populate this section header
1549
               new_shdr = (elf_section_header_t *) &new_shtab.bytes[new_debuglink_shdr_offset]; // now populate this section header
1484
               ADD_NAME_TO_STRINGTABLE (".gnu_debuglink", &elfsection_shstrtab_data, &elfsection_shstrtab_size);
1550
               ADD_NAME_TO_STRINGTABLE (".gnu_debuglink", elfsection_shstrtab);
1485
               ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in (".gnu_debuglink", elfsection_shstrtab_data, elfsection_shstrtab_size)); // update the relative offset of the section name
1551
               ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in (".gnu_debuglink", &elfsection_shstrtab)); // update the relative offset of the section name
1486
               ELF_SET_NUMERIC (elf, new_shdr, type,         ELF_GET_NUMERIC (elf, shdr, type)); // duplicate section type
1552
               ELF_SET_NUMERIC (elf, new_shdr, type,         ELF_GET_NUMERIC (elf, shdr, type)); // duplicate section type
1487
               ELF_SET_NUMERIC (elf, new_shdr, flags,        ELF_GET_NUMERIC (elf, shdr, flags)); // duplicate section flags
1553
               ELF_SET_NUMERIC (elf, new_shdr, flags,        ELF_GET_NUMERIC (elf, shdr, flags)); // duplicate section flags
1488
               ELF_SET_NUMERIC (elf, new_shdr, virtual_addr, ELF_GET_NUMERIC (elf, shdr, virtual_addr)); // duplicate section virtual address
1554
               ELF_SET_NUMERIC (elf, new_shdr, virtual_addr, ELF_GET_NUMERIC (elf, shdr, virtual_addr)); // duplicate section virtual address
1489
               ELF_SET_NUMERIC (elf, new_shdr, file_offset, (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset ? WILL_BE_FILLED_LATER : ELF_GET_NUMERIC (elf, shdr, file_offset))); // duplicate section offset only if it doesn't move
1555
               ELF_SET_NUMERIC (elf, new_shdr, file_offset, (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset ? WILL_BE_FILLED_LATER : ELF_GET_NUMERIC (elf, shdr, file_offset))); // duplicate section offset only if it doesn't move
1490
               ELF_SET_NUMERIC (elf, new_shdr, size,         ELF_GET_NUMERIC (elf, shdr, size)); // duplicate section size
1556
               ELF_SET_NUMERIC (elf, new_shdr, size,         ELF_GET_NUMERIC (elf, shdr, size)); // duplicate section size
Line 1495... Line 1561...
1495
            }
1561
            }
1496
            if ((shdr = elf_get_section_header_by_name (elf, "QNX_usage")) != NULL)
1562
            if ((shdr = elf_get_section_header_by_name (elf, "QNX_usage")) != NULL)
1497
            {
1563
            {
1498
               if (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset) // if this section needs to be moved around, have a copy of it
1564
               if (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset) // if this section needs to be moved around, have a copy of it
1499
               {
1565
               {
1500
                  elfsection_qnxusage_size = ELF_GET_NUMERIC (elf, shdr, size);
1566
                  elfsection_qnxusage.len = ELF_GET_NUMERIC (elf, shdr, size);
1501
                  elfsection_qnxusage_data = malloc (elfsection_qnxusage_size);
1567
                  elfsection_qnxusage.bytes = malloc (elfsection_qnxusage.len);
1502
                  WELLMANNERED_ASSERT (elfsection_qnxusage_data, "out of memory");
1568
                  WELLMANNERED_ASSERT (elfsection_qnxusage.bytes, "out of memory");
1503
                  memcpy (elfsection_qnxusage_data, &entry_parms->data[ELF_GET_NUMERIC (elf, shdr, file_offset)], elfsection_qnxusage_size);
1569
                  memcpy (elfsection_qnxusage.bytes, &entry_parms->data.bytes[ELF_GET_NUMERIC (elf, shdr, file_offset)], elfsection_qnxusage.len);
1504
               }
1570
               }
1505
               reallocated_ptr = realloc (new_shdr_table, new_shdr_tablesize + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more
1571
               reallocated_ptr = realloc (new_shtab.bytes, new_shtab.len + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more
1506
               WELLMANNERED_ASSERT (reallocated_ptr, "out of memory");
1572
               WELLMANNERED_ASSERT (reallocated_ptr, "out of memory");
1507
               new_shdr_table = reallocated_ptr; // reallocation succeeded, save the new pointer
1573
               new_shtab.bytes = reallocated_ptr; // reallocation succeeded, save the new pointer
1508
               new_qnxusage_shdr_offset = new_shdr_tablesize; // remember the new offset of this section header
1574
               new_qnxusage_shdr_offset = new_shtab.len; // remember the new offset of this section header
1509
               new_shdr_tablesize += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now
1575
               new_shtab.len += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now
1510
 
1576
 
1511
               new_shdr = (elf_section_header_t *) &new_shdr_table[new_qnxusage_shdr_offset]; // now populate this section header
1577
               new_shdr = (elf_section_header_t *) &new_shtab.bytes[new_qnxusage_shdr_offset]; // now populate this section header
1512
               ADD_NAME_TO_STRINGTABLE ("QNX_usage", &elfsection_shstrtab_data, &elfsection_shstrtab_size);
1578
               ADD_NAME_TO_STRINGTABLE ("QNX_usage", elfsection_shstrtab);
1513
               ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in ("QNX_usage", elfsection_shstrtab_data, elfsection_shstrtab_size)); // update the relative offset of the section name
1579
               ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in ("QNX_usage", &elfsection_shstrtab)); // update the relative offset of the section name
1514
               ELF_SET_NUMERIC (elf, new_shdr, type,         ELF_GET_NUMERIC (elf, shdr, type)); // duplicate section type
1580
               ELF_SET_NUMERIC (elf, new_shdr, type,         ELF_GET_NUMERIC (elf, shdr, type)); // duplicate section type
1515
               ELF_SET_NUMERIC (elf, new_shdr, flags,        ELF_GET_NUMERIC (elf, shdr, flags)); // duplicate section flags
1581
               ELF_SET_NUMERIC (elf, new_shdr, flags,        ELF_GET_NUMERIC (elf, shdr, flags)); // duplicate section flags
1516
               ELF_SET_NUMERIC (elf, new_shdr, virtual_addr, ELF_GET_NUMERIC (elf, shdr, virtual_addr)); // duplicate section virtual address
1582
               ELF_SET_NUMERIC (elf, new_shdr, virtual_addr, ELF_GET_NUMERIC (elf, shdr, virtual_addr)); // duplicate section virtual address
1517
               ELF_SET_NUMERIC (elf, new_shdr, file_offset, (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset ? WILL_BE_FILLED_LATER : ELF_GET_NUMERIC (elf, shdr, file_offset))); // duplicate section offset only if it doesn't move
1583
               ELF_SET_NUMERIC (elf, new_shdr, file_offset, (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset ? WILL_BE_FILLED_LATER : ELF_GET_NUMERIC (elf, shdr, file_offset))); // duplicate section offset only if it doesn't move
1518
               ELF_SET_NUMERIC (elf, new_shdr, size,         ELF_GET_NUMERIC (elf, shdr, size)); // duplicate section size
1584
               ELF_SET_NUMERIC (elf, new_shdr, size,         ELF_GET_NUMERIC (elf, shdr, size)); // duplicate section size
Line 1523... Line 1589...
1523
            }
1589
            }
1524
            if ((shdr = elf_get_section_header_by_name (elf, ".note.gnu.build-id")) != NULL)
1590
            if ((shdr = elf_get_section_header_by_name (elf, ".note.gnu.build-id")) != NULL)
1525
            {
1591
            {
1526
               if (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset) // if this section needs to be moved around, have a copy of it
1592
               if (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset) // if this section needs to be moved around, have a copy of it
1527
               {
1593
               {
1528
                  elfsection_buildid_size = ELF_GET_NUMERIC (elf, shdr, size);
1594
                  elfsection_buildid.len = ELF_GET_NUMERIC (elf, shdr, size);
1529
                  elfsection_buildid_data = malloc (elfsection_buildid_size);
1595
                  elfsection_buildid.bytes = malloc (elfsection_buildid.len);
1530
                  WELLMANNERED_ASSERT (elfsection_buildid_data, "out of memory");
1596
                  WELLMANNERED_ASSERT (elfsection_buildid.bytes, "out of memory");
1531
                  memcpy (elfsection_buildid_data, &entry_parms->data[ELF_GET_NUMERIC (elf, shdr, file_offset)], elfsection_buildid_size);
1597
                  memcpy (elfsection_buildid.bytes, &entry_parms->data.bytes[ELF_GET_NUMERIC (elf, shdr, file_offset)], elfsection_buildid.len);
1532
               }
1598
               }
1533
               reallocated_ptr = realloc (new_shdr_table, new_shdr_tablesize + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more
1599
               reallocated_ptr = realloc (new_shtab.bytes, new_shtab.len + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more
1534
               WELLMANNERED_ASSERT (reallocated_ptr, "out of memory");
1600
               WELLMANNERED_ASSERT (reallocated_ptr, "out of memory");
1535
               new_shdr_table = reallocated_ptr; // reallocation succeeded, save the new pointer
1601
               new_shtab.bytes = reallocated_ptr; // reallocation succeeded, save the new pointer
1536
               new_buildid_shdr_offset = new_shdr_tablesize; // remember the new offset of this section header
1602
               new_buildid_shdr_offset = new_shtab.len; // remember the new offset of this section header
1537
               new_shdr_tablesize += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now
1603
               new_shtab.len += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now
1538
 
1604
 
1539
               new_shdr = (elf_section_header_t *) &new_shdr_table[new_buildid_shdr_offset]; // now populate this section header
1605
               new_shdr = (elf_section_header_t *) &new_shtab.bytes[new_buildid_shdr_offset]; // now populate this section header
1540
               ADD_NAME_TO_STRINGTABLE (".note.gnu.build-id", &elfsection_shstrtab_data, &elfsection_shstrtab_size);
1606
               ADD_NAME_TO_STRINGTABLE (".note.gnu.build-id", elfsection_shstrtab);
1541
               ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in (".note.gnu.build-id", elfsection_shstrtab_data, elfsection_shstrtab_size)); // update the relative offset of the section name
1607
               ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in (".note.gnu.build-id", &elfsection_shstrtab)); // update the relative offset of the section name
1542
               ELF_SET_NUMERIC (elf, new_shdr, type,         ELF_GET_NUMERIC (elf, shdr, type)); // duplicate section type
1608
               ELF_SET_NUMERIC (elf, new_shdr, type,         ELF_GET_NUMERIC (elf, shdr, type)); // duplicate section type
1543
               ELF_SET_NUMERIC (elf, new_shdr, flags,        ELF_GET_NUMERIC (elf, shdr, flags)); // duplicate section flags
1609
               ELF_SET_NUMERIC (elf, new_shdr, flags,        ELF_GET_NUMERIC (elf, shdr, flags)); // duplicate section flags
1544
               ELF_SET_NUMERIC (elf, new_shdr, virtual_addr, ELF_GET_NUMERIC (elf, shdr, virtual_addr)); // duplicate section virtual address
1610
               ELF_SET_NUMERIC (elf, new_shdr, virtual_addr, ELF_GET_NUMERIC (elf, shdr, virtual_addr)); // duplicate section virtual address
1545
               ELF_SET_NUMERIC (elf, new_shdr, file_offset, (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset ? WILL_BE_FILLED_LATER : ELF_GET_NUMERIC (elf, shdr, file_offset))); // duplicate section offset only if it doesn't move
1611
               ELF_SET_NUMERIC (elf, new_shdr, file_offset, (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset ? WILL_BE_FILLED_LATER : ELF_GET_NUMERIC (elf, shdr, file_offset))); // duplicate section offset only if it doesn't move
1546
               ELF_SET_NUMERIC (elf, new_shdr, size,         ELF_GET_NUMERIC (elf, shdr, size)); // duplicate section size
1612
               ELF_SET_NUMERIC (elf, new_shdr, size,         ELF_GET_NUMERIC (elf, shdr, size)); // duplicate section size
1547
               ELF_SET_NUMERIC (elf, new_shdr, linked_index, ELF_GET_NUMERIC (elf, shdr, linked_index)); // duplicate section linked index (FIXME: may be wrong now!)
1613
               ELF_SET_NUMERIC (elf, new_shdr, linked_index, ELF_GET_NUMERIC (elf, shdr, linked_index)); // duplicate section linked index (FIXME: may be wrong now!)
1548
               ELF_SET_NUMERIC (elf, new_shdr, info,         ELF_GET_NUMERIC (elf, shdr, info)); // duplicate section info
1614
               ELF_SET_NUMERIC (elf, new_shdr, info,         ELF_GET_NUMERIC (elf, shdr, info)); // duplicate section info
1549
               ELF_SET_NUMERIC (elf, new_shdr, alignment,    ELF_GET_NUMERIC (elf, shdr, alignment)); // duplicate section alignment
1615
               ELF_SET_NUMERIC (elf, new_shdr, alignment,    ELF_GET_NUMERIC (elf, shdr, alignment)); // duplicate section alignment
1550
               ELF_SET_NUMERIC (elf, new_shdr, entry_size,   ELF_GET_NUMERIC (elf, shdr, entry_size)); // duplicate section entry size
1616
               ELF_SET_NUMERIC (elf, new_shdr, entry_size,   ELF_GET_NUMERIC (elf, shdr, entry_size)); // duplicate section entry size
1551
            }
1617
            }
1552
            reallocated_ptr = realloc (new_shdr_table, new_shdr_tablesize + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more
1618
            reallocated_ptr = realloc (new_shtab.bytes, new_shtab.len + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more
1553
            WELLMANNERED_ASSERT (reallocated_ptr, "out of memory");
1619
            WELLMANNERED_ASSERT (reallocated_ptr, "out of memory");
1554
            new_shdr_table = reallocated_ptr; // reallocation succeeded, save the new pointer
1620
            new_shtab.bytes = reallocated_ptr; // reallocation succeeded, save the new pointer
1555
            new_shstrtab_shdr_offset = new_shdr_tablesize; // remember the new offset of this section header
1621
            new_shstrtab_shdr_offset = new_shtab.len; // remember the new offset of this section header
1556
            new_shdr_tablesize += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now
1622
            new_shtab.len += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now
1557
 
1623
 
1558
            new_shdr = (elf_section_header_t *) &new_shdr_table[new_shstrtab_shdr_offset]; // now populate this section header
1624
            new_shdr = (elf_section_header_t *) &new_shtab.bytes[new_shstrtab_shdr_offset]; // now populate this section header
1559
            ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in (".shstrtab", elfsection_shstrtab_data, elfsection_shstrtab_size)); // update the relative offset of the section name
1625
            ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in (".shstrtab", &elfsection_shstrtab)); // update the relative offset of the section name
1560
            ELF_SET_NUMERIC (elf, new_shdr, type,         ELF_SECTIONTYPE_STRINGTABLE); // section type (SHT_STRTAB)
1626
            ELF_SET_NUMERIC (elf, new_shdr, type,         ELF_SECTIONTYPE_STRINGTABLE); // section type (SHT_STRTAB)
1561
            ELF_SET_NUMERIC (elf, new_shdr, flags,        0); // section flags (we could set SHF_STRINGS i.e. 0x20 here, but mkifs does not, so mimic that)
1627
            ELF_SET_NUMERIC (elf, new_shdr, flags,        0); // section flags (we could set SHF_STRINGS i.e. 0x20 here, but mkifs does not, so mimic that)
1562
            ELF_SET_NUMERIC (elf, new_shdr, virtual_addr, 0); // this section does not need to be mapped
1628
            ELF_SET_NUMERIC (elf, new_shdr, virtual_addr, 0); // this section does not need to be mapped
1563
            ELF_SET_NUMERIC (elf, new_shdr, file_offset, WILL_BE_FILLED_LATER); // FIXME
1629
            ELF_SET_NUMERIC (elf, new_shdr, file_offset, WILL_BE_FILLED_LATER); // will be filled once we know it
1564
            ELF_SET_NUMERIC (elf, new_shdr, size,         elfsection_shstrtab_size); // section size
1630
            ELF_SET_NUMERIC (elf, new_shdr, size,         elfsection_shstrtab.len); // section size
1565
            ELF_SET_NUMERIC (elf, new_shdr, linked_index, 0); // this section is not linked to any other
1631
            ELF_SET_NUMERIC (elf, new_shdr, linked_index, 0); // this section is not linked to any other
1566
            ELF_SET_NUMERIC (elf, new_shdr, info,         0); // this section has no additional info
1632
            ELF_SET_NUMERIC (elf, new_shdr, info,         0); // this section has no additional info
1567
            ELF_SET_NUMERIC (elf, new_shdr, alignment,    1); // this section is byte-aligned
1633
            ELF_SET_NUMERIC (elf, new_shdr, alignment,    1); // this section is byte-aligned
1568
            ELF_SET_NUMERIC (elf, new_shdr, entry_size,   0); // this section is not a table, so entry_size is zero
1634
            ELF_SET_NUMERIC (elf, new_shdr, entry_size,   0); // this section is not a table, so entry_size is zero
1569
 
1635
 
1570
            // jump over the new section headers table and write the sections that need to be relocated after the section headers table
1636
            // jump over the new section headers table and write the sections that need to be relocated after the section headers table
1571
            entry_parms->datalen = new_shdrtable_offset + new_shdr_tablesize; // assume there are no sections beyond the section headers table until known otherwise
1637
            entry_parms->data.len = new_shdrtable_offset + new_shtab.len; // assume there are no sections beyond the section headers table until known otherwise
1572
            if (elfsection_qnxinfo_data != NULL)
1638
            if (elfsection_qnxinfo.bytes != NULL)
1573
            {
-
 
1574
               memcpy (&entry_parms->data[entry_parms->datalen], elfsection_qnxinfo_data, elfsection_qnxinfo_size); // write section in place
-
 
1575
               free (elfsection_qnxinfo_data); // free it
-
 
1576
               new_shdr = (elf_section_header_t *) &new_shdr_table[new_qnxinfo_shdr_offset]; // now fix this section header
1639
               APPEND_SECTION_DATA (elfsection_qnxinfo, new_qnxinfo_shdr_offset); // write "QNX_info" section data if we have such a section
1577
               ELF_SET_NUMERIC (elf, new_shdr, file_offset, entry_parms->datalen); // fix section offset in the new section headers table
-
 
1578
               entry_parms->datalen += elfsection_qnxinfo_size; // update new ELF file length
-
 
1579
            }
-
 
1580
            if (elfsection_debuglink_data != NULL)
1640
            if (elfsection_debuglink.bytes != NULL)
1581
            {
-
 
1582
               memcpy (&entry_parms->data[entry_parms->datalen], elfsection_debuglink_data, elfsection_debuglink_size); // write section in place
-
 
1583
               free (elfsection_debuglink_data); // free it
-
 
1584
               new_shdr = (elf_section_header_t *) &new_shdr_table[new_debuglink_shdr_offset]; // now fix this section header
1641
               APPEND_SECTION_DATA (elfsection_debuglink, new_debuglink_shdr_offset); // write ".gnu_debuglink" section data if we have such a section
1585
               ELF_SET_NUMERIC (elf, new_shdr, file_offset, entry_parms->datalen); // fix section offset in the new section headers table
-
 
1586
               entry_parms->datalen += elfsection_debuglink_size; // update new ELF file length
-
 
1587
            }
-
 
1588
            if (elfsection_qnxusage_data != NULL)
1642
            if (elfsection_qnxusage.bytes != NULL)
1589
            {
-
 
1590
               memcpy (&entry_parms->data[entry_parms->datalen], elfsection_qnxusage_data, elfsection_qnxusage_size); // write section in place
-
 
1591
               free (elfsection_qnxusage_data); // free it
-
 
1592
               new_shdr = (elf_section_header_t *) &new_shdr_table[new_qnxusage_shdr_offset]; // now fix this section header
1643
               APPEND_SECTION_DATA (elfsection_qnxusage, new_qnxusage_shdr_offset); // write "QNX_usage" section data if we have such a section
1593
               ELF_SET_NUMERIC (elf, new_shdr, file_offset, entry_parms->datalen); // fix section offset in the new section headers table
-
 
1594
               entry_parms->datalen += elfsection_qnxusage_size; // update new ELF file length
-
 
1595
            }
-
 
1596
            if (elfsection_buildid_data != NULL)
1644
            if (elfsection_buildid.bytes != NULL)
1597
            {
-
 
1598
               memcpy (&entry_parms->data[entry_parms->datalen], elfsection_buildid_data, elfsection_buildid_size); // write section in place
-
 
1599
               free (elfsection_buildid_data); // free it
-
 
1600
               new_shdr = (elf_section_header_t *) &new_shdr_table[new_buildid_shdr_offset]; // now fix this section header
-
 
1601
               ELF_SET_NUMERIC (elf, new_shdr, file_offset, entry_parms->datalen); // fix section offset in the new section headers table
1645
               APPEND_SECTION_DATA (elfsection_buildid, new_buildid_shdr_offset); // write ".note.gnu.build-id" section data if we have such a section
1602
               entry_parms->datalen += elfsection_buildid_size; // update new ELF file length
-
 
1603
            }
-
 
1604
            if (elfsection_shstrtab_data != NULL)
-
 
1605
            {
-
 
1606
               memcpy (&entry_parms->data[entry_parms->datalen], elfsection_shstrtab_data, elfsection_shstrtab_size); // write section header strings table section in place
1646
            APPEND_SECTION_DATA (elfsection_shstrtab, new_shstrtab_shdr_offset); // write the section header strings table as the last section
1607
               free (elfsection_shstrtab_data);
-
 
1608
               new_shdr = (elf_section_header_t *) &new_shdr_table[new_shstrtab_shdr_offset]; // now fix this section header
-
 
1609
               ELF_SET_NUMERIC (elf, new_shdr, file_offset, entry_parms->datalen); // fix section offset in the new section headers table
-
 
1610
               entry_parms->datalen += elfsection_shstrtab_size; // update new ELF file length
-
 
1611
            }
-
 
1612
 
1647
 
1613
            // now write the section headers table
1648
            // now write the section headers table
1614
            fprintf (stderr, "rewriting section headers table at offset 0x%zd\n", new_shdrtable_offset);
-
 
1615
            memcpy (&entry_parms->data[new_shdrtable_offset], new_shdr_table, new_shdr_tablesize);
1649
            memcpy (&entry_parms->data.bytes[new_shdrtable_offset], new_shtab.bytes, new_shtab.len);
1616
            free (new_shdr_table); // free it
1650
            free (new_shtab.bytes); // free it
1617
 
1651
 
1618
            // and finally fix the ELF header
1652
            // and finally fix the ELF header
1619
            ELF_SET_NUMERIC (elf, elf, section_header_table_offset, new_shdrtable_offset);
1653
            ELF_SET_NUMERIC (elf, elf, section_header_table_offset, new_shdrtable_offset);
1620
            ELF_SET_NUMERIC (elf, elf, section_header_table_len, new_shdr_tablesize / ELF_STRUCT_SIZE (elf, shdr));
1654
            ELF_SET_NUMERIC (elf, elf, section_header_table_len, new_shtab.len / ELF_STRUCT_SIZE (elf, shdr));
1621
            ELF_SET_NUMERIC (elf, elf, section_header_names_idx, new_shdr_tablesize / ELF_STRUCT_SIZE (elf, shdr) - 1); // the section headers strings table is the last section
1655
            ELF_SET_NUMERIC (elf, elf, section_header_names_idx, new_shtab.len / ELF_STRUCT_SIZE (elf, shdr) - 1); // the section headers strings table is the last section
1622
 
1656
 
1623
            // align size with page size (4096 on x86, 16k on ARM)
1657
            // align size with page size (4096 on x86, 16k on ARM)
1624
            end_padding_offset = entry_parms->datalen;
1658
            end_padding_offset = entry_parms->data.len;
1625
            if (ELF_GET_NUMERIC (elf, elf, instruction_set) == ELF_MACHINE_X86_64)
1659
            if (ELF_GET_NUMERIC (elf, elf, instruction_set) == ELF_MACHINE_X86_64)
1626
               entry_parms->datalen = ROUND_TO_UPPER_MULTIPLE (end_padding_offset, 4 * 1024); // 4 kb pages on Intel processors
1660
               entry_parms->data.len = ROUND_TO_UPPER_MULTIPLE (end_padding_offset, 4 * 1024); // 4 kb pages on Intel processors
1627
            else if (ELF_GET_NUMERIC (elf, elf, instruction_set) == ELF_MACHINE_AARCH64)
1661
            else if (ELF_GET_NUMERIC (elf, elf, instruction_set) == ELF_MACHINE_AARCH64)
1628
               entry_parms->datalen = ROUND_TO_UPPER_MULTIPLE (end_padding_offset, 16 * 1024); // 16 kb pages on ARM64
1662
               entry_parms->data.len = ROUND_TO_UPPER_MULTIPLE (end_padding_offset, 16 * 1024); // 16 kb pages on ARM64
1629
            else
1663
            else
1630
            {
1664
            {
1631
               fprintf (stderr, "fatal error: this ELF file \"%s\" does not belong to an architecture supported by ifstool (neither x86_64, nor aarch64)\n", stored_pathname);
1665
               fprintf (stderr, "fatal error: this ELF file \"%s\" does not belong to an architecture supported by ifstool (neither x86_64, nor aarch64)\n", stored_pathname);
1632
               exit (1);
1666
               exit (1);
1633
            }
1667
            }
1634
            memset (&entry_parms->data[end_padding_offset], 0, entry_parms->datalen - end_padding_offset); // zerofill
1668
            memset (&entry_parms->data.bytes[end_padding_offset], 0, entry_parms->data.len - end_padding_offset); // zerofill
1635
 
1669
 
1636
            entry_parms->extra_ino_flags |= IFS_INO_PROCESSED_ELF; // mark this inode as a preprocessed ELF file
1670
            entry_parms->extra_ino_flags |= IFS_INO_PROCESSED_ELF; // mark this inode as a preprocessed ELF file
1637
         } // end if the file is not yet a processed ELF
1671
         } // end if the file is not yet a processed ELF
1638
      } // end if the file we're storing is an ELF file
1672
      } // end if the file we're storing is an ELF file
1639
   }
1673
   }
1640
   else if (S_ISLNK (entry_parms->st_mode)) // else are we storing a symbolic link ?
1674
   else if (S_ISLNK (entry_parms->st_mode)) // else are we storing a symbolic link ?
1641
      fprintf (stderr, "symlink: ino 0x%x uid %d gid %d mode 0%o path \"%s\" -> \"%s\"\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data);
1675
      fprintf (stderr, "symlink: ino 0x%x uid %d gid %d mode 0%o path \"%s\" -> \"%s\"\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data.bytes);
1642
   else // we must be storing a FIFO
1676
   else // we must be storing a FIFO
1643
   {
1677
   {
1644
      if (strchr (entry_parms->data, ':') == NULL)
1678
      if (strchr (entry_parms->data.bytes, ':') == NULL)
1645
      {
1679
      {
1646
         fprintf (stderr, "fatal error: device entry \"%s\" malformed (no 'dev:rdev' pair)\n", stored_pathname);
1680
         fprintf (stderr, "fatal error: device entry \"%s\" malformed (no 'dev:rdev' pair)\n", stored_pathname);
1647
         exit (1);
1681
         exit (1);
1648
      }
1682
      }
1649
      fprintf (stderr, "fifo: ino 0x%x uid %d gid %d mode 0%o path \"%s\" dev rdev %s)\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data);
1683
      fprintf (stderr, "fifo: ino 0x%x uid %d gid %d mode 0%o path \"%s\" dev rdev %s)\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data.bytes);
1650
   }
1684
   }
1651
 
1685
 
1652
   // grow filesystem entries array to hold one more slot
1686
   // grow filesystem entries array to hold one more slot
1653
   reallocated_ptr = realloc (*fsentries, (*fsentry_count + 1) * sizeof (fsentry_t)); // attempt to reallocate
1687
   reallocated_ptr = realloc (*fsentries, (*fsentry_count + 1) * sizeof (fsentry_t)); // attempt to reallocate
1654
   if (reallocated_ptr == NULL)
1688
   if (reallocated_ptr == NULL)
Line 1672... Line 1706...
1672
      fsentry->UNSAVED_was_data_written = true; // no data to save
1706
      fsentry->UNSAVED_was_data_written = true; // no data to save
1673
   }
1707
   }
1674
   else if (S_ISREG (entry_parms->st_mode))
1708
   else if (S_ISREG (entry_parms->st_mode))
1675
   {
1709
   {
1676
      fsentry->u.file.offset = WILL_BE_FILLED_LATER; // will be filled later in main() when the file's data blob will be written to the output file
1710
      fsentry->u.file.offset = WILL_BE_FILLED_LATER; // will be filled later in main() when the file's data blob will be written to the output file
1677
      fsentry->u.file.size = (uint32_t) entry_parms->datalen;
1711
      fsentry->u.file.size = (uint32_t) entry_parms->data.len;
1678
      fsentry->u.file.path = strdup (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname);
1712
      fsentry->u.file.path = strdup (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname);
1679
      fsentry->u.file.UNSAVED_databuf = malloc (entry_parms->datalen);
1713
      fsentry->u.file.UNSAVED_databuf = malloc (entry_parms->data.len);
1680
      WELLMANNERED_ASSERT (fsentry->u.file.UNSAVED_databuf, "out of memory");
1714
      WELLMANNERED_ASSERT (fsentry->u.file.UNSAVED_databuf, "out of memory");
1681
      memcpy (fsentry->u.file.UNSAVED_databuf, entry_parms->data, entry_parms->datalen);
1715
      memcpy (fsentry->u.file.UNSAVED_databuf, entry_parms->data.bytes, entry_parms->data.len);
1682
      fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint32_t) + sizeof (uint32_t) + strlen (fsentry->u.file.path) + 1, image_align); // now we can set the size
1716
      fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint32_t) + sizeof (uint32_t) + strlen (fsentry->u.file.path) + 1, image_align); // now we can set the size
1683
      fsentry->UNSAVED_was_data_written = false; // there *IS* data to save
1717
      fsentry->UNSAVED_was_data_written = false; // there *IS* data to save
1684
   }
1718
   }
1685
   else if (S_ISLNK (entry_parms->st_mode))
1719
   else if (S_ISLNK (entry_parms->st_mode))
1686
   {
1720
   {
1687
      fsentry->u.symlink.sym_offset = (uint16_t) (strlen (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname) + 1);
1721
      fsentry->u.symlink.sym_offset = (uint16_t) (strlen (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname) + 1);
1688
      fsentry->u.symlink.sym_size = (uint16_t) entry_parms->datalen;
1722
      fsentry->u.symlink.sym_size = (uint16_t) entry_parms->data.len;
1689
      fsentry->u.symlink.path = strdup (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname);
1723
      fsentry->u.symlink.path = strdup (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname);
1690
      fsentry->u.symlink.contents = strdup (entry_parms->data);
1724
      fsentry->u.symlink.contents = strdup (entry_parms->data.bytes);
1691
      WELLMANNERED_ASSERT (fsentry->u.symlink.contents, "out of memory");
1725
      WELLMANNERED_ASSERT (fsentry->u.symlink.contents, "out of memory");
1692
      fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint16_t) + sizeof (uint16_t) + (size_t) fsentry->u.symlink.sym_offset + fsentry->u.symlink.sym_size + 1, image_align); // now we can set the size
1726
      fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint16_t) + sizeof (uint16_t) + (size_t) fsentry->u.symlink.sym_offset + fsentry->u.symlink.sym_size + 1, image_align); // now we can set the size
1693
      fsentry->UNSAVED_was_data_written = true; // no data to save
1727
      fsentry->UNSAVED_was_data_written = true; // no data to save
1694
   }
1728
   }
1695
   else // necessarily a device node
1729
   else // necessarily a device node
1696
   {
1730
   {
1697
      fsentry->u.device.dev  = strtol (entry_parms->data, NULL, 0); // use strtol() to parse decimal (...), hexadecimal (0x...) and octal (0...) numbers
1731
      fsentry->u.device.dev  = strtol (entry_parms->data.bytes, NULL, 0); // use strtol() to parse decimal (...), hexadecimal (0x...) and octal (0...) numbers
1698
      fsentry->u.device.rdev = strtol (strchr (entry_parms->data, ':') + 1, NULL, 0); // use strtol() to parse decimal (...), hexadecimal (0x...) and octal (0...) numbers
1732
      fsentry->u.device.rdev = strtol (strchr (entry_parms->data.bytes, ':') + 1, NULL, 0); // use strtol() to parse decimal (...), hexadecimal (0x...) and octal (0...) numbers
1699
      fsentry->u.device.path = strdup (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname);
1733
      fsentry->u.device.path = strdup (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname);
1700
      fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint32_t) + sizeof (uint32_t) + strlen (fsentry->u.device.path), image_align); // now we can set the size
1734
      fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint32_t) + sizeof (uint32_t) + strlen (fsentry->u.device.path), image_align); // now we can set the size
1701
      fsentry->UNSAVED_was_data_written = true; // no data to save
1735
      fsentry->UNSAVED_was_data_written = true; // no data to save
1702
   }
1736
   }
1703
   (*fsentry_count)++;
1737
   (*fsentry_count)++;
Line 1709... Line 1743...
1709
      entry_parms->should_autosymlink_dylib = false;
1743
      entry_parms->should_autosymlink_dylib = false;
1710
      entry_parms->should_follow_symlinks = false;
1744
      entry_parms->should_follow_symlinks = false;
1711
      entry_parms->st_mode = S_IFLNK | 0777; // NOTE: mkifs stores symlink permissions as rwxrwxrwx !
1745
      entry_parms->st_mode = S_IFLNK | 0777; // NOTE: mkifs stores symlink permissions as rwxrwxrwx !
1712
      entry_parms->extra_ino_flags = (fsentry->header.ino & (IFS_INO_PROCESSED_ELF | IFS_INO_RUNONCE_ELF | IFS_INO_BOOTSTRAP_EXE)); // preserve target's inode flags
1746
      entry_parms->extra_ino_flags = (fsentry->header.ino & (IFS_INO_PROCESSED_ELF | IFS_INO_RUNONCE_ELF | IFS_INO_BOOTSTRAP_EXE)); // preserve target's inode flags
1713
      last_dirsep = strrchr (stored_pathname, '/');
1747
      last_dirsep = strrchr (stored_pathname, '/');
1714
      old_data = entry_parms->data; // backup previous data pointer
1748
      old_data = entry_parms->data.bytes; // backup previous data pointer
1715
      entry_parms->data = (uint8_t *) (last_dirsep == NULL ? stored_pathname : last_dirsep + 1); // store symlink target in dirent data
1749
      entry_parms->data.bytes = (uint8_t *) (last_dirsep == NULL ? stored_pathname : last_dirsep + 1); // store symlink target in dirent data
1716
      entry_parms->datalen = strlen (entry_parms->data);
1750
      entry_parms->data.len = strlen (entry_parms->data.bytes);
1717
      add_fsentry (fsentries, fsentry_count, entry_parms, original_stored_pathname, NULL);
1751
      add_fsentry (fsentries, fsentry_count, entry_parms, original_stored_pathname, NULL);
1718
      entry_parms->data = old_data; // restore previous data pointer so that it can be freed normally
1752
      entry_parms->data.bytes = old_data; // restore previous data pointer so that it can be freed normally
1719
   }
1753
   }
1720
 
1754
 
1721
   return (*fsentry_count);
1755
   return (*fsentry_count);
1722
}
1756
}
1723
 
1757
 
Line 1801... Line 1835...
1801
      .should_follow_symlinks = true, // [+|-followlink]
1835
      .should_follow_symlinks = true, // [+|-followlink]
1802
      .should_autosymlink_dylib = true, // [+|-autolink]
1836
      .should_autosymlink_dylib = true, // [+|-autolink]
1803
      .is_compiled_bootscript = false, // [+|-script]
1837
      .is_compiled_bootscript = false, // [+|-script]
1804
      .extra_ino_flags = 0,
1838
      .extra_ino_flags = 0,
1805
      .search = "",
1839
      .search = "",
1806
      .data = NULL,
1840
      .data = { NULL, 0 }
1807
      .datalen = 0
-
 
1808
   };
1841
   };
1809
   static parms_t entry_parms = { 0 }; // current parameters for a filesystem entry (will be initialized to default_parms each time a new entry is parsed in the build file)
1842
   static parms_t entry_parms = { 0 }; // current parameters for a filesystem entry (will be initialized to default_parms each time a new entry is parsed in the build file)
1810
 
1843
 
1811
   // bootable IFS support
1844
   // bootable IFS support
1812
   char *bootfile_pathname = NULL;           // HACK: pathname to bootcode binary blob file to put at the start of a bootable IFS
1845
   char *bootfile_pathname = NULL;           // HACK: pathname to bootcode binary blob file to put at the start of a bootable IFS
Line 1826... Line 1859...
1826
   struct stat stat_buf;
1859
   struct stat stat_buf;
1827
   size_t startuptrailer_offset;
1860
   size_t startuptrailer_offset;
1828
   size_t startupheader_offset;
1861
   size_t startupheader_offset;
1829
   size_t imagetrailer_offset;
1862
   size_t imagetrailer_offset;
1830
   size_t imageheader_offset;
1863
   size_t imageheader_offset;
-
 
1864
   size_t corrective_offset;
1831
   size_t imgdir_offset;
1865
   size_t imgdir_offset;
1832
   size_t imgdir_size;
1866
   size_t imgdir_size;
1833
   size_t final_size;
1867
   size_t final_size;
1834
   size_t blob_size;
-
 
1835
   size_t available_space;
1868
   size_t available_space;
1836
   size_t allocated_size;
1869
   size_t allocated_size;
1837
   size_t fsentry_index;
1870
   size_t fsentry_index;
1838
   size_t largest_index;
1871
   size_t largest_index;
1839
   size_t largest_size;
1872
   size_t largest_size;
1840
   size_t curr_offset;
1873
   size_t curr_offset;
1841
   size_t table_index;
1874
   size_t table_index;
1842
   size_t table_count;
1875
   size_t table_count;
1843
   uint8_t *blob_data;
1876
   buffer_t blob;
1844
   int32_t checksum;
1877
   int32_t checksum;
1845
   char *specifiedpathname_start;
1878
   char *specifiedpathname_start;
1846
   char *directiveblock_start;
1879
   char *directiveblock_start;
1847
   char *write_ptr;
1880
   char *write_ptr;
1848
   char *line_ptr;
1881
   char *line_ptr;
Line 1851... Line 1884...
1851
   char *sep;
1884
   char *sep;
1852
   //char *ctx;
1885
   //char *ctx;
1853
   int arg_index;
1886
   int arg_index;
1854
   bool is_quoted_context = false;
1887
   bool is_quoted_context = false;
1855
   bool is_escaped_char = false;
1888
   bool is_escaped_char = false;
1856
   bool has_data_already = false;
1889
   bool should_discard_inline_contents = false;
1857
   bool want_info = false;
1890
   bool want_info = false;
1858
   bool want_everything = false;
1891
   bool want_everything = false;
1859
   bool want_help = false;
1892
   bool want_help = false;
1860
   bool is_foreign_endianness;
1893
   bool is_foreign_endianness;
1861
   int string_len;
1894
   int string_len;
Line 1894... Line 1927...
1894
      }
1927
      }
1895
      else if (strcmp (argv[arg_index], "-n") == 0)
1928
      else if (strcmp (argv[arg_index], "-n") == 0)
1896
         default_parms.mtime_for_inline_files = 0; // inline files should have a mtime set to zero
1929
         default_parms.mtime_for_inline_files = 0; // inline files should have a mtime set to zero
1897
      else if (strcmp (argv[arg_index], "-nn") == 0)
1930
      else if (strcmp (argv[arg_index], "-nn") == 0)
1898
      {
1931
      {
1899
         default_parms.mtime = 0; // all files should have a mtime set to zero
1932
         default_parms.mtime = 0; // *all* files should have a mtime set to zero
1900
         default_parms.mtime_for_inline_files = 0;
1933
         default_parms.mtime_for_inline_files = 0;
1901
      }
1934
      }
1902
      else if (strcmp (argv[arg_index], "--info") == 0)
1935
      else if (strcmp (argv[arg_index], "--info") == 0)
1903
         want_info = true;
1936
         want_info = true;
1904
      else if (strcmp (argv[arg_index], "--everything") == 0)
1937
      else if (strcmp (argv[arg_index], "--everything") == 0)
Line 1920... Line 1953...
1920
         fprintf (stderr, "error: missing parameters\n");
1953
         fprintf (stderr, "error: missing parameters\n");
1921
      fprintf ((want_help ? stdout : stderr), "usage:\n");
1954
      fprintf ((want_help ? stdout : stderr), "usage:\n");
1922
      fprintf ((want_help ? stdout : stderr), "    ifstool [--bootfile <pathname>] [--startupfile <pathname>@<EP_from_imgbase>] [--kernelfile <pathname>@<fileoffs>] [-n[n]] <buildfile> <outfile>\n");
1955
      fprintf ((want_help ? stdout : stderr), "    ifstool [--bootfile <pathname>] [--startupfile <pathname>@<EP_from_imgbase>] [--kernelfile <pathname>@<fileoffs>] [-n[n]] <buildfile> <outfile>\n");
1923
      fprintf ((want_help ? stdout : stderr), "    ifstool --info [--everything] <ifs file>\n");
1956
      fprintf ((want_help ? stdout : stderr), "    ifstool --info [--everything] <ifs file>\n");
1924
      fprintf ((want_help ? stdout : stderr), "    ifstool --help\n");
1957
      fprintf ((want_help ? stdout : stderr), "    ifstool --help\n");
1925
      fprintf ((want_help ? stdout : stderr), "WARNING: the compilation feature is currently a work in progress (broken). Only the --info mode is usable at the moment.\n");
1958
      fprintf ((want_help ? stdout : stderr), "NOTE: the compilation feature requires predigested boot, startup and kernel files produced by mkifs.\n");
1926
      exit (want_help ? 0 : 1);
1959
      exit (want_help ? 0 : 1);
1927
   }
1960
   }
1928
 
1961
 
1929
   // do we want info about a particular IFS ? if so, dump it
1962
   // do we want info about a particular IFS ? if so, dump it
1930
   if (want_info)
1963
   if (want_info)
Line 1957... Line 1990...
1957
   // stack up filesystem entries
1990
   // stack up filesystem entries
1958
   memcpy (&entry_parms, &default_parms, sizeof (default_parms));
1991
   memcpy (&entry_parms, &default_parms, sizeof (default_parms));
1959
   entry_parms.st_mode = S_IFDIR | default_parms.dperms;
1992
   entry_parms.st_mode = S_IFDIR | default_parms.dperms;
1960
   add_fsentry (&fsentries, &fsentry_count, &entry_parms, "", NULL); // add the root dir first
1993
   add_fsentry (&fsentries, &fsentry_count, &entry_parms, "", NULL); // add the root dir first
1961
 
1994
 
-
 
1995
   // parse the IFS build file line per line
1962
   while (fgets (line_buffer, sizeof (line_buffer), buildfile_fp) != NULL)
1996
   while (fgets (line_buffer, sizeof (line_buffer), buildfile_fp) != NULL)
1963
   {
1997
   {
1964
      if (current_line != NULL)
1998
      if (current_line != NULL)
1965
         free (current_line);
1999
         free (current_line);
1966
      current_line = strdup (line_buffer);
2000
      current_line = strdup (line_buffer);
1967
      WELLMANNERED_ASSERT (current_line, "out of memory");
2001
      WELLMANNERED_ASSERT (current_line, "out of memory");
1968
      lineno++; // keep track of current line number
2002
      lineno++; // keep track of current line number
1969
      //fprintf (stderr, "read buildfile line %d: {%s}\n", lineno, line_buffer);
-
 
1970
 
2003
 
1971
      line_ptr = line_buffer;
2004
      line_ptr = line_buffer;
1972
      while ((*line_ptr != 0) && isspace (*line_ptr))
2005
      while ((*line_ptr != 0) && isspace (*line_ptr))
1973
         line_ptr++; // skip leading spaces
2006
         line_ptr++; // skip leading spaces
1974
 
2007
 
Line 1981... Line 2014...
1981
 
2014
 
1982
      // reset entry values
2015
      // reset entry values
1983
      memcpy (&entry_parms, &default_parms, sizeof (default_parms));
2016
      memcpy (&entry_parms, &default_parms, sizeof (default_parms));
1984
      path_in_ifs[0] = 0;
2017
      path_in_ifs[0] = 0;
1985
      path_on_buildhost[0] = 0;
2018
      path_on_buildhost[0] = 0;
1986
      has_data_already = false;
2019
      should_discard_inline_contents = false;
1987
 
-
 
1988
      //fprintf (stderr, "parsing buildfile line %d: [%s]\n", lineno, line_ptr);
-
 
1989
 
2020
 
1990
      // does this line start with an attribute block ?
2021
      // does this line start with an attribute block ?
1991
      if (*line_ptr == '[')
2022
      if (*line_ptr == '[')
1992
      {
2023
      {
1993
         line_ptr++; // skip the leading square bracket
2024
         line_ptr++; // skip the leading square bracket
Line 2049... Line 2080...
2049
                  fprintf (stderr, "error: unable to stat the boot file \"%s\" specified in \"%s\" line %d: %s\n", bootfile_pathname, buildfile_pathname, lineno, strerror (errno));
2080
                  fprintf (stderr, "error: unable to stat the boot file \"%s\" specified in \"%s\" line %d: %s\n", bootfile_pathname, buildfile_pathname, lineno, strerror (errno));
2050
                  exit (1);
2081
                  exit (1);
2051
               }
2082
               }
2052
               bootfile_size = stat_buf.st_size; // save preboot file size
2083
               bootfile_size = stat_buf.st_size; // save preboot file size
2053
               fprintf (stderr, "info: processor \"%s\" bootfile \"%s\"\n", image_processor, bootfile_pathname);
2084
               fprintf (stderr, "info: processor \"%s\" bootfile \"%s\"\n", image_processor, bootfile_pathname);
-
 
2085
#if 1
-
 
2086
               // ######################################################################################################################################################################################################################################
-
 
2087
               // # FIXME: figure out how to re-create it: linker call involved
-
 
2088
               // # $ x86_64-pc-nto-qnx8.0.0-ld --sysroot=${QNX_TARGET}/x86_64/ -T${QNX_TARGET}/x86_64/lib/nto.link --section-start .text=0xffff800000001000 --no-relax ${QNX_TARGET}/x86_64/boot/sys/procnto-smp-instr -o procnto-smp-instr.sym.UNSTRIPPED
-
 
2089
               // ######################################################################################################################################################################################################################################
2054
               if (read_filecontents (kernelfile_pathname, ".", &entry_parms.data, &entry_parms.datalen) == NULL)
2090
               if (read_filecontents (kernelfile_pathname, ".", &entry_parms.data) == NULL)
2055
               {
2091
               {
2056
                  fprintf (stderr, "fatal error: unable to read precompiled kernel file \"%s\" specified in --kernelfile argument\n", kernelfile_pathname);
2092
                  fprintf (stderr, "fatal error: unable to read precompiled kernel file \"%s\" specified in --kernelfile argument\n", kernelfile_pathname);
2057
                  exit (1);
2093
                  exit (1);
2058
               }
2094
               }
-
 
2095
#else // nonworking
-
 
2096
               strcpy (path_on_buildhost, "procnto-smp-instr");
-
 
2097
#endif // nonworking
-
 
2098
 
2059
               has_data_already = true; // remember we already have data
2099
               should_discard_inline_contents = true; // remember we already have data (so as to discard the inline block's contents)
2060
            }
2100
            }
2061
            else if (strncmp (token, "mtime=", 6) == 0) { REACH_TOKEN_VALUE (); if (strcmp (value, "*") == 0) entry_parms.mtime = UINT32_MAX; else {
2101
            else if (strncmp (token, "mtime=", 6) == 0) { REACH_TOKEN_VALUE (); if (strcmp (value, "*") == 0) entry_parms.mtime = UINT32_MAX; else {
2062
                  // value *must* be "YYYY-MM-DD-HH:MM:SS" by specification
2102
                  // value *must* be "YYYY-MM-DD-HH:MM:SS" by specification
2063
                  memset (&utc_time, 0, sizeof (utc_time));
2103
                  memset (&utc_time, 0, sizeof (utc_time));
2064
                  if (sscanf (value, "%u-%u-%u-%u:%u:%u", &utc_time.tm_year, &utc_time.tm_mon, &utc_time.tm_mday, &utc_time.tm_hour, &utc_time.tm_min, &utc_time.tm_sec) != 6)
2104
                  if (sscanf (value, "%u-%u-%u-%u:%u:%u", &utc_time.tm_year, &utc_time.tm_mon, &utc_time.tm_mday, &utc_time.tm_hour, &utc_time.tm_min, &utc_time.tm_sec) != 6)
Line 2070... Line 2110...
2070
                  entry_parms.mtime = (uint32_t) mktime (&utc_time);
2110
                  entry_parms.mtime = (uint32_t) mktime (&utc_time);
2071
               }
2111
               }
2072
            }
2112
            }
2073
            else if (strcmp (token, "+script")     == 0) {
2113
            else if (strcmp (token, "+script")     == 0) {
2074
               entry_parms.is_compiled_bootscript = true;
2114
               entry_parms.is_compiled_bootscript = true;
2075
               entry_parms.data = malloc (sizeof (INITIAL_STARTUP_SCRIPT) - 1);
2115
               entry_parms.data.bytes = malloc (sizeof (INITIAL_STARTUP_SCRIPT) - 1);
2076
               WELLMANNERED_ASSERT (entry_parms.data, "out of memory");
2116
               WELLMANNERED_ASSERT (entry_parms.data.bytes, "out of memory");
2077
               memcpy (entry_parms.data, INITIAL_STARTUP_SCRIPT, sizeof (INITIAL_STARTUP_SCRIPT) - 1); // FIXME: HACK until the script compiler is implemented
2117
               memcpy (entry_parms.data.bytes, INITIAL_STARTUP_SCRIPT, sizeof (INITIAL_STARTUP_SCRIPT) - 1); // FIXME: HACK until the script compiler is implemented
2078
               entry_parms.datalen = sizeof (INITIAL_STARTUP_SCRIPT) - 1;
2118
               entry_parms.data.len = sizeof (INITIAL_STARTUP_SCRIPT) - 1;
2079
               has_data_already = true; // remember we already have data
2119
               should_discard_inline_contents = true; // remember we already have data (so as to discard the inline block's contents)
2080
            }
2120
            }
2081
            else if (strcmp (token, "-script")     == 0) entry_parms.is_compiled_bootscript = false;
2121
            else if (strcmp (token, "-script")     == 0) entry_parms.is_compiled_bootscript = false;
2082
            else if (strcmp (token, "+followlink") == 0) entry_parms.should_follow_symlinks = true;
2122
            else if (strcmp (token, "+followlink") == 0) entry_parms.should_follow_symlinks = true;
2083
            else if (strcmp (token, "-followlink") == 0) entry_parms.should_follow_symlinks = false;
2123
            else if (strcmp (token, "-followlink") == 0) entry_parms.should_follow_symlinks = false;
2084
            else if (strcmp (token, "+autolink")   == 0) entry_parms.should_autosymlink_dylib = true;
2124
            else if (strcmp (token, "+autolink")   == 0) entry_parms.should_autosymlink_dylib = true;
Line 2168... Line 2208...
2168
         }
2208
         }
2169
 
2209
 
2170
         // read the host system's path, it may be either a path or a contents definition. Is it a content definition ?
2210
         // read the host system's path, it may be either a path or a contents definition. Is it a content definition ?
2171
         if (*line_ptr == '{')
2211
         if (*line_ptr == '{')
2172
         {
2212
         {
2173
            path_on_buildhost[0] = 0; // this is an inline fine, which means it doesn't exist on the build host
-
 
2174
            allocated_size = 0;
2213
            allocated_size = 0;
2175
 
2214
 
2176
            line_ptr++; // skip the leading content definition
2215
            line_ptr++; // skip the leading content definition
2177
            is_escaped_char = false;
2216
            is_escaped_char = false;
2178
            for (;;)
2217
            for (;;)
Line 2188... Line 2227...
2188
               else if ((read_char == '}') && !is_escaped_char)
2227
               else if ((read_char == '}') && !is_escaped_char)
2189
                  break; // found an unescaped closing bracked, stop parsing
2228
                  break; // found an unescaped closing bracked, stop parsing
2190
               else
2229
               else
2191
               {
2230
               {
2192
                  is_escaped_char = false; // any other char, meaning the next one will not be escaped
2231
                  is_escaped_char = false; // any other char, meaning the next one will not be escaped
2193
                  if (!has_data_already) // only store the contents if we do NOT know the data yet
2232
                  if (!should_discard_inline_contents) // only store the contents if we do NOT know the data yet
2194
                  {
2233
                  {
2195
                     if (entry_parms.datalen == allocated_size) // reallocate in 4 kb blocks
2234
                     if (entry_parms.data.len == allocated_size) // reallocate in 4 kb blocks
2196
                     {
2235
                     {
2197
                        reallocated_ptr = realloc (entry_parms.data, allocated_size + 4096);
2236
                        reallocated_ptr = realloc (entry_parms.data.bytes, allocated_size + 4096);
2198
                        WELLMANNERED_ASSERT (reallocated_ptr, "out of memory");
2237
                        WELLMANNERED_ASSERT (reallocated_ptr != NULL, "out of memory");
2199
                        entry_parms.data = reallocated_ptr;
2238
                        entry_parms.data.bytes = reallocated_ptr;
2200
                        allocated_size += 4096;
2239
                        allocated_size += 4096;
2201
                     }
2240
                     }
2202
                     entry_parms.data[entry_parms.datalen++] = read_char;
2241
                     entry_parms.data.bytes[entry_parms.data.len++] = read_char;
2203
                  }
2242
                  }
2204
                  if (read_char == '\n')
2243
                  if (read_char == '\n')
2205
                     lineno++; // update line counter as we parse the inline content
2244
                     lineno++; // update line counter as we parse the inline content
2206
               }
2245
               }
2207
            } // end for
2246
            } // end for
2208
            has_data_already = true; // remember we have data now
-
 
2209
         }
2247
         }
2210
         else // not a content definition between { brackets }, must be either a pathname on the build host, or the target of a symlink
2248
         else // not a content definition between { brackets }, must be either a pathname on the build host, or the target of a symlink
2211
         {
2249
         {
2212
            is_quoted_context = (*line_ptr == '"');
2250
            is_quoted_context = (*line_ptr == '"');
2213
            if (is_quoted_context)
2251
            if (is_quoted_context)
Line 2229... Line 2267...
2229
            if (is_quoted_context && (*line_ptr == '"'))
2267
            if (is_quoted_context && (*line_ptr == '"'))
2230
               line_ptr++; // skip a possible final quote
2268
               line_ptr++; // skip a possible final quote
2231
 
2269
 
2232
            if (S_ISLNK (entry_parms.st_mode)) // are we storing a symlink ?
2270
            if (S_ISLNK (entry_parms.st_mode)) // are we storing a symlink ?
2233
            {
2271
            {
2234
               entry_parms.data = strdup (specifiedpathname_start); // if so, store the symlink target as the dirent's blob data
2272
               entry_parms.data.bytes = strdup (specifiedpathname_start); // if so, store the symlink target as the dirent's blob data
2235
               WELLMANNERED_ASSERT (entry_parms.data, "out of memory");
2273
               WELLMANNERED_ASSERT (entry_parms.data.bytes != NULL, "out of memory");
2236
               entry_parms.datalen = strlen (specifiedpathname_start);
2274
               entry_parms.data.len = strlen (specifiedpathname_start);
2237
               has_data_already = true; // remember we have data now
-
 
2238
            }
2275
            }
2239
            else // it's a build host filesystem path
2276
            else // it's a build host filesystem path
2240
               strcpy (path_on_buildhost, line_ptr); // the path on the build host is given after the equal sign
2277
               strcpy (path_on_buildhost, line_ptr); // the path on the build host is given after the equal sign
2241
         }
2278
         }
2242
      }
2279
      }
Line 2263... Line 2300...
2263
      else // file or device node
2300
      else // file or device node
2264
         entry_parms.st_mode |= entry_parms.perms;
2301
         entry_parms.st_mode |= entry_parms.perms;
2265
 
2302
 
2266
      add_fsentry (&fsentries, &fsentry_count, &entry_parms, path_in_ifs, path_on_buildhost); // and add filesystem entry
2303
      add_fsentry (&fsentries, &fsentry_count, &entry_parms, path_in_ifs, path_on_buildhost); // and add filesystem entry
2267
 
2304
 
2268
      if (entry_parms.data != NULL)
2305
      if (entry_parms.data.bytes != NULL)
2269
         free (entry_parms.data); // if blob data was allocated, free it
2306
         free (entry_parms.data.bytes); // if blob data was allocated, free it
2270
   }
2307
   }
2271
 
2308
 
2272
   // write IFS file
2309
   // write IFS file
2273
   fp = fopen (ifs_pathname, "w+b");
2310
   fp = fopen (ifs_pathname, "w+b");
2274
   if (fp == NULL)
2311
   if (fp == NULL)
Line 2279... Line 2316...
2279
 
2316
 
2280
   // do we have a startup file ? if so, this is a bootable image
2317
   // do we have a startup file ? if so, this is a bootable image
2281
   if (startupfile_pathname != NULL)
2318
   if (startupfile_pathname != NULL)
2282
   {
2319
   {
2283
      // write boot prefix
2320
      // write boot prefix
-
 
2321
      // ######################################################################################################################################################################################################################################
-
 
2322
      // # FIXME: figure out how to re-create it
-
 
2323
      // ######################################################################################################################################################################################################################################
2284
      fwrite_filecontents (bootfile_pathname, fp);
2324
      fwrite_filecontents (bootfile_pathname, fp);
2285
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
2325
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
2286
 
2326
 
2287
      startupheader_offset = ftell (fp); // save startup header offset
2327
      startupheader_offset = ftell (fp); // save startup header offset
2288
      memset (&startup_header, 0, sizeof (startup_header)); // prepare startup header
2328
      memset (&startup_header, 0, sizeof (startup_header)); // prepare startup header
Line 2309... Line 2349...
2309
      startup_header.preboot_size  = (uint16_t) bootfile_size;                              // [I ] Size of loaded before header, here 0xf30 or 3888 bytes (size of "bios.boot" file))
2349
      startup_header.preboot_size  = (uint16_t) bootfile_size;                              // [I ] Size of loaded before header, here 0xf30 or 3888 bytes (size of "bios.boot" file))
2310
      fwrite_or_die (&startup_header, 1, sizeof (startup_header), fp); // write startup header
2350
      fwrite_or_die (&startup_header, 1, sizeof (startup_header), fp); // write startup header
2311
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
2351
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
2312
 
2352
 
2313
      // ######################################################################################################################################################################################################################################
2353
      // ######################################################################################################################################################################################################################################
2314
      // # FIXME: figure out how to re-create it: linker call involved
2354
      // # FIXME: figure out how to re-create it:
-
 
2355
      // first: open "startup-x86" ELF file,
-
 
2356
      //        lookup section headers table (there is no program headers table in this one)
-
 
2357
      //        FIXME: figure out something in there where the result is 0x1401030 !!!
2315
      // # $ x86_64-pc-nto-qnx8.0.0-ld --sysroot=${QNX_TARGET}/x86_64/ -T${QNX_TARGET}/x86_64/lib/nto.link --section-start .text=0x1401030 --no-relax ${QNX_TARGET}/x86_64/boot/sys/startup-x86 -o startup.bin.UNSTRIPPED
2358
      // then: call the linker: ld --sysroot=${QNX_TARGET}/x86_64/ -T${QNX_TARGET}/x86_64/lib/nto.link --section-start .text=0x1401030 --no-relax ${QNX_TARGET}/x86_64/boot/sys/startup-x86 -o startup.bin.UNSTRIPPED
-
 
2359
      // then: parse resulting ELF file, take all program segments and concatenate them --> this is the blob (FIXME: wrong?)
2316
      // ######################################################################################################################################################################################################################################
2360
      // ######################################################################################################################################################################################################################################
-
 
2361
#if 0 // nonworking
-
 
2362
      {
-
 
2363
         buffer_t startupfile;
-
 
2364
         elf_section_header_t *shdr_text;
-
 
2365
         size_t segment_len;
-
 
2366
FILE *control_fp = fopen ("startup.bin.MYSTRIPPED", "wb");
-
 
2367
 
-
 
2368
         if (read_filecontents ("startup.bin.UNSTRIPPED", MKIFS_PATH, &startupfile) == NULL)
-
 
2369
         {
-
 
2370
            fprintf (stderr, "fatal error: couldn't read startup-x86\n");
-
 
2371
            exit (1);
-
 
2372
         }
-
 
2373
         elf = (elf_header_t *) startupfile.bytes; // quick access to ELF header
-
 
2374
         table_count = ELF_GET_NUMERIC (elf, elf, program_header_table_len); // get the number of program headers
-
 
2375
         for (table_index = 0; table_index < table_count; table_index++) // cycle through program headers
-
 
2376
         {
-
 
2377
            phdr = (elf_program_header_t *) &startupfile.bytes[ELF_GET_NUMERIC (elf, elf, program_header_table_offset) + (size_t) ELF_GET_NUMERIC (elf, elf, program_header_item_size) * table_index]; // quick access to program header
-
 
2378
            segment_len = ELF_GET_NUMERIC (elf, phdr, size_in_file);
-
 
2379
            fwrite_or_die (&startupfile.bytes[ELF_GET_NUMERIC (elf, phdr, file_offset)], 1, segment_len, fp); // dump program segment
-
 
2380
fwrite_or_die (&startupfile.bytes[ELF_GET_NUMERIC (elf, phdr, file_offset)], 1, segment_len, control_fp); // dump program segment
-
 
2381
while (segment_len % 4096 > 0)
-
 
2382
{
-
 
2383
   fputc (0, control_fp);
-
 
2384
   segment_len++;
-
 
2385
}
-
 
2386
         }
-
 
2387
 
-
 
2388
fclose (control_fp);
-
 
2389
         free (startupfile.bytes);
-
 
2390
      }
-
 
2391
#else // working
2317
      fwrite_filecontents (startupfile_pathname, fp); // write startup code from blob file
2392
      fwrite_filecontents (startupfile_pathname, fp); // write startup code from blob file
-
 
2393
#endif // working
2318
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
2394
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
2319
 
2395
 
2320
      startuptrailer_offset = ftell (fp); // save startup trailer offset
2396
      startuptrailer_offset = ftell (fp); // save startup trailer offset
2321
      fwrite_or_die (&startup_trailer, 1, sizeof (startup_trailer), fp); // write startup trailer
2397
      fwrite_or_die (&startup_trailer, 1, sizeof (startup_trailer), fp); // write startup trailer
2322
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
2398
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
Line 2383... Line 2459...
2383
               largest_index = fsentry_index;
2459
               largest_index = fsentry_index;
2384
            }
2460
            }
2385
         }
2461
         }
2386
         if (largest_size == 0)
2462
         if (largest_size == 0)
2387
            break; // found none ? if so, stop searching
2463
            break; // found none ? if so, stop searching
-
 
2464
 
-
 
2465
         fsentries[largest_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure
2388
 
2466
 
2389
         // is the file we're storing a preprocessed ELF file ?
2467
         // is the file we're storing a preprocessed ELF file ?
2390
         if (fsentries[fsentry_index].header.ino & IFS_INO_PROCESSED_ELF)
2468
         if (fsentries[largest_index].header.ino & IFS_INO_PROCESSED_ELF)
2391
         {
2469
         {
2392
            elf = (elf_header_t *) fsentries[fsentry_index].u.file.UNSAVED_databuf; // quick access to ELF header
2470
            elf = (elf_header_t *) fsentries[largest_index].u.file.UNSAVED_databuf; // quick access to ELF header
2393
            table_count = ELF_GET_NUMERIC (elf, elf, program_header_table_len); // get the number of program headers
2471
            table_count = ELF_GET_NUMERIC (elf, elf, program_header_table_len); // get the number of program headers
2394
            for (table_index = 0; table_index < table_count; table_index++)
2472
            for (table_index = 0; table_index < table_count; table_index++)
2395
            {
2473
            {
2396
               phdr = (elf_program_header_t *) &fsentries[fsentry_index].u.file.UNSAVED_databuf[ELF_GET_NUMERIC (elf, elf, program_header_table_offset) + (size_t) ELF_GET_NUMERIC (elf, elf, program_header_item_size) * table_index]; // quick access to program header
2474
               phdr = (elf_program_header_t *) &fsentries[largest_index].u.file.UNSAVED_databuf[ELF_GET_NUMERIC (elf, elf, program_header_table_offset) + (size_t) ELF_GET_NUMERIC (elf, elf, program_header_item_size) * table_index]; // quick access to program header
-
 
2475
               corrective_offset = ELF_GET_NUMERIC (elf, phdr, virtual_addr) - ELF_GET_NUMERIC (elf, phdr, file_offset);
-
 
2476
               if (ELF_GET_NUMERIC (elf, phdr, size_in_memory) != 0) // only patch the physical address of segments that have an actual size in memory
2397
               ELF_SET_NUMERIC (elf, phdr, physical_addr, ELF_GET_NUMERIC (elf, phdr, physical_addr) + (0x1400000 + curr_offset)); // patch the physical address member of the program header table
2477
                  ELF_SET_NUMERIC (elf, phdr, physical_addr, ELF_GET_NUMERIC (elf, phdr, physical_addr) + 0x1400000 + curr_offset - corrective_offset); // patch the physical address member of the program header table
2398
            }
2478
            }
2399
         }
2479
         }
2400
 
2480
 
2401
         fsentries[largest_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure
-
 
2402
         fwrite_or_die (fsentries[largest_index].u.file.UNSAVED_databuf, 1, fsentries[largest_index].u.file.size, fp); // write file data blob
2481
         fwrite_or_die (fsentries[largest_index].u.file.UNSAVED_databuf, 1, fsentries[largest_index].u.file.size, fp); // write file data blob
2403
         fsentries[largest_index].UNSAVED_was_data_written = true; // and remember this file's data was written
2482
         fsentries[largest_index].UNSAVED_was_data_written = true; // and remember this file's data was written
2404
      }
2483
      }
2405
      fprintf (stderr, "Current offset: 0x%zx\n", curr_offset);
2484
      fprintf (stderr, "Current offset: 0x%zx\n", curr_offset);
2406
      fprintf (stderr, "Kernel file offset: 0x%zx\n", kernelfile_offset);
2485
      fprintf (stderr, "Kernel file offset: 0x%zx\n", kernelfile_offset);
Line 2410... Line 2489...
2410
      for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++)
2489
      for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++)
2411
         if (fsentries[fsentry_index].header.ino == image_kernel_ino)
2490
         if (fsentries[fsentry_index].header.ino == image_kernel_ino)
2412
            break; // locate the kernel directory entry (can't fail)
2491
            break; // locate the kernel directory entry (can't fail)
2413
      curr_offset = ftell (fp); // see where we are
2492
      curr_offset = ftell (fp); // see where we are
2414
      fsentries[fsentry_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure
2493
      fsentries[fsentry_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure
2415
      // ######################################################################################################################################################################################################################################
-
 
2416
      // # FIXME: figure out how to re-create it: linker call involved
-
 
2417
      // # $ x86_64-pc-nto-qnx8.0.0-ld --sysroot=${QNX_TARGET}/x86_64/ -T${QNX_TARGET}/x86_64/lib/nto.link --section-start .text=0xffff800000001000 --no-relax ${QNX_TARGET}/x86_64/boot/sys/procnto-smp-instr -o procnto-smp-instr.sym.UNSTRIPPED
-
 
2418
      // ######################################################################################################################################################################################################################################
-
 
2419
      fwrite_filecontents (kernelfile_pathname, fp); // write kernel from blob file
2494
      fwrite_or_die (fsentries[fsentry_index].u.file.UNSAVED_databuf, 1, fsentries[fsentry_index].u.file.size, fp); // write kernel file data blob
2420
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
2495
      PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary
2421
      fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written
2496
      fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written
2422
   }
2497
   }
2423
 
2498
 
2424
   // then write all the other files by increasing inode number: ELF files first
2499
   // then write all the other files by increasing inode number: ELF files first
Line 2436... Line 2511...
2436
         elf = (elf_header_t *) fsentries[fsentry_index].u.file.UNSAVED_databuf; // quick access to ELF header
2511
         elf = (elf_header_t *) fsentries[fsentry_index].u.file.UNSAVED_databuf; // quick access to ELF header
2437
         table_count = ELF_GET_NUMERIC (elf, elf, program_header_table_len); // get the number of program headers
2512
         table_count = ELF_GET_NUMERIC (elf, elf, program_header_table_len); // get the number of program headers
2438
         for (table_index = 0; table_index < table_count; table_index++)
2513
         for (table_index = 0; table_index < table_count; table_index++)
2439
         {
2514
         {
2440
            phdr = (elf_program_header_t *) &fsentries[fsentry_index].u.file.UNSAVED_databuf[ELF_GET_NUMERIC (elf, elf, program_header_table_offset) + (size_t) ELF_GET_NUMERIC (elf, elf, program_header_item_size) * table_index]; // quick access to program header
2515
            phdr = (elf_program_header_t *) &fsentries[fsentry_index].u.file.UNSAVED_databuf[ELF_GET_NUMERIC (elf, elf, program_header_table_offset) + (size_t) ELF_GET_NUMERIC (elf, elf, program_header_item_size) * table_index]; // quick access to program header
-
 
2516
            corrective_offset = ELF_GET_NUMERIC (elf, phdr, virtual_addr) - ELF_GET_NUMERIC (elf, phdr, file_offset);
-
 
2517
            if (ELF_GET_NUMERIC (elf, phdr, size_in_memory) != 0) // only patch the physical address of segments that have an actual size in memory
2441
            ELF_SET_NUMERIC (elf, phdr, physical_addr, ELF_GET_NUMERIC (elf, phdr, physical_addr) + (0x1400000 + curr_offset)); // patch the physical address member of the program header table
2518
               ELF_SET_NUMERIC (elf, phdr, physical_addr, ELF_GET_NUMERIC (elf, phdr, physical_addr) + 0x1400000 + curr_offset - corrective_offset); // patch the physical address member of the program header table
2442
         }
2519
         }
2443
      }
2520
      }
2444
 
2521
 
2445
      fwrite_or_die (fsentries[fsentry_index].u.file.UNSAVED_databuf, 1, fsentries[fsentry_index].u.file.size, fp); // write file data blob
2522
      fwrite_or_die (fsentries[fsentry_index].u.file.UNSAVED_databuf, 1, fsentries[fsentry_index].u.file.size, fp); // write file data blob
2446
      fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written
2523
      fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written
Line 2477... Line 2554...
2477
   {
2554
   {
2478
      // rewrite startup header with final values
2555
      // rewrite startup header with final values
2479
      fseek_or_die (fp, startupheader_offset, SEEK_SET);
2556
      fseek_or_die (fp, startupheader_offset, SEEK_SET);
2480
      startup_header.startup_size = (uint32_t) (imageheader_offset - startupheader_offset); // size of startup header up to image header
2557
      startup_header.startup_size = (uint32_t) (imageheader_offset - startupheader_offset); // size of startup header up to image header
2481
      startup_header.imagefs_size = (uint32_t) (final_size - imageheader_offset); // size of uncompressed imagefs
2558
      startup_header.imagefs_size = (uint32_t) (final_size - imageheader_offset); // size of uncompressed imagefs
2482
      startup_header.ram_size = (uint32_t) final_size; // FIXME: this is necessarily less, but should we really bother calculating the right size ?
2559
      startup_header.ram_size     = (uint32_t) (final_size - startupheader_offset);
2483
      startup_header.stored_size = (uint32_t) final_size;
2560
      startup_header.stored_size  = (uint32_t) (final_size - startupheader_offset);
2484
      fwrite_or_die (&startup_header, 1, sizeof (startup_header), fp); // write startup header
2561
      fwrite_or_die (&startup_header, 1, sizeof (startup_header), fp); // write startup header
2485
   }
2562
   }
2486
 
2563
 
2487
   // rewrite image header with final values
2564
   // rewrite image header with final values
2488
   fseek_or_die (fp, imageheader_offset, SEEK_SET);
2565
   fseek_or_die (fp, imageheader_offset, SEEK_SET);
Line 2499... Line 2576...
2499
 
2576
 
2500
   fclose (fp); // ensure everything is flushed
2577
   fclose (fp); // ensure everything is flushed
2501
 
2578
 
2502
   // ALL CHECKSUMS AT THE VERY END
2579
   // ALL CHECKSUMS AT THE VERY END
2503
 
2580
 
2504
   blob_data = NULL;
-
 
2505
   read_filecontents (ifs_pathname, ".", &blob_data, &blob_size);
2581
   read_filecontents (ifs_pathname, ".", &blob);
2506
   WELLMANNERED_ASSERT (blob_data, "failed to open IFS file for checksumming: %s", strerror (errno));
2582
   WELLMANNERED_ASSERT (blob.bytes != NULL, "failed to open IFS file for checksumming: %s", strerror (errno));
2507
 
2583
 
2508
   // do we have a startup file ? if so, this is a bootable image
2584
   // do we have a startup file ? if so, this is a bootable image
2509
   if (startupfile_pathname != NULL)
2585
   if (startupfile_pathname != NULL)
2510
   {
2586
   {
2511
      // compute SHA-512 checksum and V1 checksum of startup block
2587
      // compute SHA-512 checksum and V1 checksum of startup block
Line 2513... Line 2589...
2513
          || (!(startup_header.flags1 & STARTUP_HDR_FLAGS1_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
2589
          || (!(startup_header.flags1 & STARTUP_HDR_FLAGS1_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
2514
         is_foreign_endianness = true; // if the header is big endian and we're on a little endian machine, or the other way around, it's a foreign endianness
2590
         is_foreign_endianness = true; // if the header is big endian and we're on a little endian machine, or the other way around, it's a foreign endianness
2515
      else
2591
      else
2516
         is_foreign_endianness = false; // else this header is for the same endianness as us
2592
         is_foreign_endianness = false; // else this header is for the same endianness as us
2517
 
2593
 
2518
      SHA512 (&blob_data[startupheader_offset], startuptrailer_offset - startupheader_offset, &blob_data[startuptrailer_offset]); // compute SHA512 checksum and write it in place in blob data
2594
      SHA512 (&blob.bytes[startupheader_offset], startuptrailer_offset - startupheader_offset, &blob.bytes[startuptrailer_offset]); // compute SHA512 checksum and write it in place in blob data
2519
      checksum = update_checksum (&blob_data[startupheader_offset], startuptrailer_offset + SHA512_DIGEST_LENGTH - startupheader_offset, is_foreign_endianness); // compute old checksum
2595
      checksum = update_checksum (&blob.bytes[startupheader_offset], startuptrailer_offset + SHA512_DIGEST_LENGTH - startupheader_offset, is_foreign_endianness); // compute old checksum
2520
      memcpy (&blob_data[startuptrailer_offset + SHA512_DIGEST_LENGTH], &checksum, 4); // and write it in place
2596
      memcpy (&blob.bytes[startuptrailer_offset + SHA512_DIGEST_LENGTH], &checksum, 4); // and write it in place
2521
   }
2597
   }
2522
 
2598
 
2523
   // compute SHA-512 checksum and V1 checksum of image block
2599
   // compute SHA-512 checksum and V1 checksum of image block
2524
   if (   ( (image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
2600
   if (   ( (image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
2525
       || (!(image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
2601
       || (!(image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
2526
      is_foreign_endianness = true; // if the header is big endian and we're on a little endian machine, or the other way around, it's a foreign endianness
2602
      is_foreign_endianness = true; // if the header is big endian and we're on a little endian machine, or the other way around, it's a foreign endianness
2527
   else
2603
   else
2528
      is_foreign_endianness = false; // else this header is for the same endianness as us
2604
      is_foreign_endianness = false; // else this header is for the same endianness as us
2529
 
2605
 
2530
   SHA512 (&blob_data[imageheader_offset], imagetrailer_offset - imageheader_offset, &blob_data[imagetrailer_offset]); // compute SHA512 checksum and write it in place in blob data
2606
   SHA512 (&blob.bytes[imageheader_offset], imagetrailer_offset - imageheader_offset, &blob.bytes[imagetrailer_offset]); // compute SHA512 checksum and write it in place in blob data
2531
   checksum = update_checksum (&blob_data[imageheader_offset], imagetrailer_offset + SHA512_DIGEST_LENGTH - imageheader_offset, is_foreign_endianness); // compute old checksum
2607
   checksum = update_checksum (&blob.bytes[imageheader_offset], imagetrailer_offset + SHA512_DIGEST_LENGTH - imageheader_offset, is_foreign_endianness); // compute old checksum
2532
   memcpy (&blob_data[imagetrailer_offset + SHA512_DIGEST_LENGTH], &checksum, 4); // and write it in place
2608
   memcpy (&blob.bytes[imagetrailer_offset + SHA512_DIGEST_LENGTH], &checksum, 4); // and write it in place
2533
 
2609
 
2534
   // now rewrite IFS with the correct checksums
2610
   // now rewrite IFS with the correct checksums
2535
   fp = fopen (ifs_pathname, "wb");
2611
   fp = fopen (ifs_pathname, "wb");
2536
   WELLMANNERED_ASSERT (fp, "failed to reopen IFS file for checksumming: %s", strerror (errno));
2612
   WELLMANNERED_ASSERT (fp, "failed to reopen IFS file for checksumming: %s", strerror (errno));
2537
   fwrite_or_die (blob_data, 1, blob_size, fp);
2613
   fwrite_or_die (blob.bytes, 1, blob.len, fp);
2538
   fclose (fp);
2614
   fclose (fp);
2539
   free (blob_data);
2615
   free (blob.bytes);
2540
 
2616
 
2541
   // finished, exit with a success code
2617
   // finished, exit with a success code
2542
   fprintf (stdout, "Success\n");
2618
   fprintf (stdout, "Success\n");
2543
   exit (0);
2619
   exit (0);
2544
}
2620
}
Line 2601... Line 2677...
2601
   size_t nearest_distance;
2677
   size_t nearest_distance;
2602
   size_t nearest_index;
2678
   size_t nearest_index;
2603
   size_t byte_index;
2679
   size_t byte_index;
2604
   uint32_t recorded_checksum;
2680
   uint32_t recorded_checksum;
2605
   uint32_t computed_checksum;
2681
   uint32_t computed_checksum;
2606
   uint8_t *filedata;
-
 
2607
   size_t filesize;
2682
   buffer_t file;
2608
   time_t mtime;
2683
   time_t mtime;
2609
 
2684
 
2610
   // open and read IFS file
2685
   // open and read IFS file
2611
   if (read_filecontents (ifs_pathname, ".", &filedata, &filesize) == NULL)
2686
   if (read_filecontents (ifs_pathname, ".", &file) == NULL)
2612
   {
2687
   {
2613
      fprintf (stderr, "error: can't open \"%s\" for reading: %s\n", ifs_pathname, strerror (errno));
2688
      fprintf (stderr, "error: can't open \"%s\" for reading: %s\n", ifs_pathname, strerror (errno));
2614
      return (1);
2689
      return (1);
2615
   }
2690
   }
2616
 
2691
 
2617
   printf ("QNX In-kernel Filesystem analysis produced by ifstool version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD);
2692
   printf ("QNX In-kernel Filesystem analysis produced by ifstool version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD);
2618
   printf ("IFS file \"%s\" - size 0x%zx (%zd) bytes\n", ifs_pathname, filesize, filesize);
2693
   printf ("IFS file \"%s\" - size 0x%zx (%zd) bytes\n", ifs_pathname, file.len, file.len);
2619
 
2694
 
2620
   // parse file from start to end
2695
   // parse file from start to end
2621
   current_offset = 0;
2696
   current_offset = 0;
2622
   for (;;)
2697
   for (;;)
2623
   {
2698
   {
2624
      // does a startup header start here ?
2699
      // does a startup header start here ?
2625
      if ((current_offset + sizeof (startup_header_t) < filesize) && (memcmp (&filedata[current_offset], "\xeb\x7e\xff\x00", 4) == 0))
2700
      if ((current_offset + sizeof (startup_header_t) < file.len) && (memcmp (&file.bytes[current_offset], "\xeb\x7e\xff\x00", 4) == 0))
2626
      {
2701
      {
2627
         startupheader_offset = current_offset;
2702
         startupheader_offset = current_offset;
2628
         startup_header = (startup_header_t *) &filedata[startupheader_offset];
2703
         startup_header = (startup_header_t *) &file.bytes[startupheader_offset];
2629
 
2704
 
2630
         // layout:
2705
         // layout:
2631
         // [STARTUP HEADER]
2706
         // [STARTUP HEADER]
2632
         // (startup file blob)
2707
         // (startup file blob)
2633
         // [STARTUP TRAILER v1 or v2]
2708
         // [STARTUP TRAILER v1 or v2]
Line 2643... Line 2718...
2643
         printf ("   startup_vaddr = 0x%08x (%d) - virtual address to transfer to after IPL is done\n", startup_header->startup_vaddr, startup_header->startup_vaddr);
2718
         printf ("   startup_vaddr = 0x%08x (%d) - virtual address to transfer to after IPL is done\n", startup_header->startup_vaddr, startup_header->startup_vaddr);
2644
         printf ("   paddr_bias    = 0x%08x (%d) - value to add to physical addresses to get an indirectable pointer value\n", startup_header->paddr_bias, startup_header->paddr_bias);
2719
         printf ("   paddr_bias    = 0x%08x (%d) - value to add to physical addresses to get an indirectable pointer value\n", startup_header->paddr_bias, startup_header->paddr_bias);
2645
         printf ("   image_paddr   = 0x%08x (%d) - physical address of image\n", startup_header->image_paddr, startup_header->image_paddr);
2720
         printf ("   image_paddr   = 0x%08x (%d) - physical address of image\n", startup_header->image_paddr, startup_header->image_paddr);
2646
         printf ("   ram_paddr     = 0x%08x (%d) - physical address of RAM to copy image to (startup_size bytes copied)\n", startup_header->ram_paddr, startup_header->ram_paddr);
2721
         printf ("   ram_paddr     = 0x%08x (%d) - physical address of RAM to copy image to (startup_size bytes copied)\n", startup_header->ram_paddr, startup_header->ram_paddr);
2647
         printf ("   ram_size      = 0x%08x (%d) - amount of RAM used by the startup program and executables in the fs\n", startup_header->ram_size, startup_header->ram_size);
2722
         printf ("   ram_size      = 0x%08x (%d) - amount of RAM used by the startup program and executables in the fs\n", startup_header->ram_size, startup_header->ram_size);
2648
         printf ("   startup_size  = 0x%08x (%d) - size of startup (never compressed) - %s\n", startup_header->startup_size, startup_header->startup_size, (current_offset + sizeof (image_header_t) + startup_header->startup_size + (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? sizeof (image_trailer_v2_t) : sizeof (image_trailer_v1_t)) < filesize ? "looks good" : "BAD (IFS file too short)"));
2723
         printf ("   startup_size  = 0x%08x (%d) - size of startup (never compressed) - %s\n", startup_header->startup_size, startup_header->startup_size, (current_offset + sizeof (image_header_t) + startup_header->startup_size + (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? sizeof (image_trailer_v2_t) : sizeof (image_trailer_v1_t)) < file.len ? "looks good" : "BAD (IFS file too short)"));
2649
         printf ("   stored_size   = 0x%08x (%d) - size of entire image - %s\n", startup_header->stored_size, startup_header->stored_size, (startup_header->stored_size == startup_header->ram_size ? "looks good" : "???"));
2724
         printf ("   stored_size   = 0x%08x (%d) - size of entire image - %s\n", startup_header->stored_size, startup_header->stored_size, (startup_header->stored_size == startup_header->ram_size ? "looks good" : "???"));
2650
         printf ("   imagefs_paddr = 0x%08x (%d) - set by IPL when startup runs - %s\n", startup_header->imagefs_paddr, startup_header->imagefs_paddr, (startup_header->imagefs_paddr == 0 ? "looks good" : "??? should be zero"));
2725
         printf ("   imagefs_paddr = 0x%08x (%d) - set by IPL when startup runs - %s\n", startup_header->imagefs_paddr, startup_header->imagefs_paddr, (startup_header->imagefs_paddr == 0 ? "looks good" : "??? should be zero"));
2651
         printf ("   imagefs_size  = 0x%08x (%d) - size of uncompressed imagefs\n", startup_header->imagefs_size, startup_header->imagefs_size);
2726
         printf ("   imagefs_size  = 0x%08x (%d) - size of uncompressed imagefs\n", startup_header->imagefs_size, startup_header->imagefs_size);
2652
         printf ("   preboot_size  = 0x%04x (%d) - size of loaded before header - %s\n", startup_header->preboot_size, startup_header->preboot_size, (startup_header->preboot_size == current_offset ? "looks good" : "???"));
2727
         printf ("   preboot_size  = 0x%04x (%d) - size of loaded before header - %s\n", startup_header->preboot_size, startup_header->preboot_size, (startup_header->preboot_size == current_offset ? "looks good" : "???"));
2653
         printf ("   zero0         = 0x%04x (%d) - zeros - %s\n", startup_header->zero0, startup_header->zero0, (startup_header->zero0 == 0 ? "looks good" : "??? should be zero"));
2728
         printf ("   zero0         = 0x%04x (%d) - zeros - %s\n", startup_header->zero0, startup_header->zero0, (startup_header->zero0 == 0 ? "looks good" : "??? should be zero"));
2654
         printf ("   zero[0]       = 0x%08x (%d) - zeros - %s\n", startup_header->zero[0], startup_header->zero[0], (startup_header->zero[0] == 0 ? "looks good" : "??? should be zero"));
2729
         printf ("   zero[0]       = 0x%08x (%d) - zeros - %s\n", startup_header->zero[0], startup_header->zero[0], (startup_header->zero[0] == 0 ? "looks good" : "??? should be zero"));
2655
         printf ("   addr_off      = 0x%016llx (%lld) - offset for startup_vaddr and [image|ram|imagefs]_paddr - %s\n", startup_header->addr_off, startup_header->addr_off, (startup_header->addr_off == 0 ? "looks good" : "??? should be zero"));
2730
         printf ("   addr_off      = 0x%016llx (%lld) - offset for startup_vaddr and [image|ram|imagefs]_paddr - %s\n", startup_header->addr_off, startup_header->addr_off, (startup_header->addr_off == 0 ? "looks good" : "??? should be zero"));
2656
         hex_printf ((uint8_t *) &startup_header->info[0], sizeof (startup_header->info), "   info[48] =\n");
2731
         hex_printf ((uint8_t *) &startup_header->info[0], sizeof (startup_header->info), "   info[48] =\n");
2657
 
2732
 
2658
         // validate that the file can contain up to the startup trailer
2733
         // validate that the file can contain up to the startup trailer
2659
         if (current_offset + startup_header->startup_size > filesize)
2734
         if (current_offset + startup_header->startup_size > file.len)
2660
         {
2735
         {
2661
            printf ("WARNING: this IFS file is corrupted (startup trailer extends past end of file)\n");
2736
            printf ("WARNING: this IFS file is corrupted (startup trailer extends past end of file)\n");
2662
            goto endofdata;
2737
            goto endofdata;
2663
         }
2738
         }
2664
 
2739
 
Line 2671... Line 2746...
2671
 
2746
 
2672
         // locate the right startup trailer at the right offset
2747
         // locate the right startup trailer at the right offset
2673
         if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2)
2748
         if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2)
2674
         {
2749
         {
2675
            startuptrailer_offset = current_offset + startup_header->startup_size - sizeof (startup_trailer_v2_t);
2750
            startuptrailer_offset = current_offset + startup_header->startup_size - sizeof (startup_trailer_v2_t);
2676
            startup_trailer_v2 = (startup_trailer_v2_t *) &filedata[startuptrailer_offset];
2751
            startup_trailer_v2 = (startup_trailer_v2_t *) &file.bytes[startuptrailer_offset];
2677
            startupfile_blobsize = startup_header->startup_size - sizeof (startup_header_t) - sizeof (startup_trailer_v2_t);
2752
            startupfile_blobsize = startup_header->startup_size - sizeof (startup_header_t) - sizeof (startup_trailer_v2_t);
2678
         }
2753
         }
2679
         else // old V1 trailer
2754
         else // old V1 trailer
2680
         {
2755
         {
2681
            startuptrailer_offset = current_offset + startup_header->startup_size - sizeof (startup_trailer_v1_t);
2756
            startuptrailer_offset = current_offset + startup_header->startup_size - sizeof (startup_trailer_v1_t);
2682
            startup_trailer_v1 = (startup_trailer_v1_t *) &filedata[startuptrailer_offset];
2757
            startup_trailer_v1 = (startup_trailer_v1_t *) &file.bytes[startuptrailer_offset];
2683
            startupfile_blobsize = startup_header->startup_size - sizeof (startup_header_t) - sizeof (startup_trailer_v1_t);
2758
            startupfile_blobsize = startup_header->startup_size - sizeof (startup_header_t) - sizeof (startup_trailer_v1_t);
2684
         }
2759
         }
2685
 
2760
 
2686
         current_offset += sizeof (startup_header_t); // jump over the startup header and reach the startup blob
2761
         current_offset += sizeof (startup_header_t); // jump over the startup header and reach the startup blob
2687
         printf ("\n");
2762
         printf ("\n");
2688
         printf ("Startup blob at offset 0x%zx (%zd):\n", current_offset, current_offset);
2763
         printf ("Startup blob at offset 0x%zx (%zd):\n", current_offset, current_offset);
2689
         printf ("   size 0x%zx (%zd) bytes\n", startupfile_blobsize, startupfile_blobsize);
2764
         printf ("   size 0x%zx (%zd) bytes\n", startupfile_blobsize, startupfile_blobsize);
2690
         printf ("   checksum %d\n", update_checksum (&filedata[current_offset], startupfile_blobsize, is_foreign_endianness));
2765
         printf ("   checksum %d\n", update_checksum (&file.bytes[current_offset], startupfile_blobsize, is_foreign_endianness));
2691
 
2766
 
2692
         current_offset += startupfile_blobsize; // jump over the startup blob and reach the startup trailer
2767
         current_offset += startupfile_blobsize; // jump over the startup blob and reach the startup trailer
2693
         printf ("\n");
2768
         printf ("\n");
2694
         printf ("Startup trailer at offset 0x%zx (%zd) - version %d:\n", current_offset, current_offset, (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? 2 : 1));
2769
         printf ("Startup trailer at offset 0x%zx (%zd) - version %d:\n", current_offset, current_offset, (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? 2 : 1));
2695
         if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2)
2770
         if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2)
Line 2717... Line 2792...
2717
 
2792
 
2718
         current_offset += (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? sizeof (startup_trailer_v2_t) : sizeof (startup_trailer_v1_t)); // now reach the next segment
2793
         current_offset += (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? sizeof (startup_trailer_v2_t) : sizeof (startup_trailer_v1_t)); // now reach the next segment
2719
      }
2794
      }
2720
 
2795
 
2721
      // else does an image header start here ?
2796
      // else does an image header start here ?
2722
      else if ((current_offset + sizeof (image_header_t) < filesize) && (memcmp (&filedata[current_offset], "imagefs", 7) == 0))
2797
      else if ((current_offset + sizeof (image_header_t) < file.len) && (memcmp (&file.bytes[current_offset], "imagefs", 7) == 0))
2723
      {
2798
      {
2724
         imageheader_offset = current_offset;
2799
         imageheader_offset = current_offset;
2725
         image_header = (image_header_t *) &filedata[imageheader_offset];
2800
         image_header = (image_header_t *) &file.bytes[imageheader_offset];
2726
 
2801
 
2727
         // layout:
2802
         // layout:
2728
         // [IMAGE HEADER]
2803
         // [IMAGE HEADER]
2729
         // [image directory entries]
2804
         // [image directory entries]
2730
         // [smallest file blobs up to KERNEL]
2805
         // [smallest file blobs up to KERNEL]
Line 2735... Line 2810...
2735
 
2810
 
2736
         printf ("\n");
2811
         printf ("\n");
2737
         printf ("Image header at offset %zx (%zd):\n", current_offset, current_offset);
2812
         printf ("Image header at offset %zx (%zd):\n", current_offset, current_offset);
2738
         printf ("   signature    = %02x %02x %02x %02x %02x %02x %02x (\"%.7s\") - good\n", image_header->signature[0], image_header->signature[1], image_header->signature[2], image_header->signature[3], image_header->signature[4], image_header->signature[5], image_header->signature[6], image_header->signature);
2813
         printf ("   signature    = %02x %02x %02x %02x %02x %02x %02x (\"%.7s\") - good\n", image_header->signature[0], image_header->signature[1], image_header->signature[2], image_header->signature[3], image_header->signature[4], image_header->signature[5], image_header->signature[6], image_header->signature);
2739
         printf ("   flags        = 0x%02x (%s)\n", image_header->flags, describe_uint8 (image_header->flags, imageheader_flags_strings));
2814
         printf ("   flags        = 0x%02x (%s)\n", image_header->flags, describe_uint8 (image_header->flags, imageheader_flags_strings));
2740
         printf ("   image_size   = 0x%08x (%d) - size from header to end of trailer - %s\n", image_header->image_size, image_header->image_size, (current_offset + image_header->image_size <= filesize ? "looks good" : "BAD (IFS file too short)"));
2815
         printf ("   image_size   = 0x%08x (%d) - size from header to end of trailer - %s\n", image_header->image_size, image_header->image_size, (current_offset + image_header->image_size <= file.len ? "looks good" : "BAD (IFS file too short)"));
2741
         printf ("   hdr_dir_size = 0x%08x (%d) - size from header to last dirent - %s\n", image_header->hdr_dir_size, image_header->hdr_dir_size, (current_offset + image_header->hdr_dir_size < filesize ? "looks good" : "BAD (IFS file too short)"));
2816
         printf ("   hdr_dir_size = 0x%08x (%d) - size from header to last dirent - %s\n", image_header->hdr_dir_size, image_header->hdr_dir_size, (current_offset + image_header->hdr_dir_size < file.len ? "looks good" : "BAD (IFS file too short)"));
2742
         printf ("   dir_offset   = 0x%08x (%d) - offset from header to first dirent - %s\n", image_header->dir_offset, image_header->dir_offset, (current_offset + image_header->dir_offset >= filesize ? "BAD (IFS file too short)" : (image_header->dir_offset > image_header->hdr_dir_size ? "BAD" : "looks good")));
2817
         printf ("   dir_offset   = 0x%08x (%d) - offset from header to first dirent - %s\n", image_header->dir_offset, image_header->dir_offset, (current_offset + image_header->dir_offset >= file.len ? "BAD (IFS file too short)" : (image_header->dir_offset > image_header->hdr_dir_size ? "BAD" : "looks good")));
2743
         printf ("   boot_ino[4]  = { 0x%08x, 0x%08x, 0x%08x, 0x%08x }\n", image_header->boot_ino[0], image_header->boot_ino[1], image_header->boot_ino[2], image_header->boot_ino[3]);
2818
         printf ("   boot_ino[4]  = { 0x%08x, 0x%08x, 0x%08x, 0x%08x }\n", image_header->boot_ino[0], image_header->boot_ino[1], image_header->boot_ino[2], image_header->boot_ino[3]);
2744
         printf ("   script_ino   = 0x%08x (%d) - inode of compiled bootscript\n", image_header->script_ino, image_header->script_ino);
2819
         printf ("   script_ino   = 0x%08x (%d) - inode of compiled bootscript\n", image_header->script_ino, image_header->script_ino);
2745
         printf ("   chain_paddr  = 0x%08x (%d) - offset to next fs signature\n", image_header->chain_paddr, image_header->chain_paddr);
2820
         printf ("   chain_paddr  = 0x%08x (%d) - offset to next fs signature\n", image_header->chain_paddr, image_header->chain_paddr);
2746
         hex_printf ((uint8_t *) &image_header->spare[0], sizeof (image_header->spare), "   spare[10] =\n");
2821
         hex_printf ((uint8_t *) &image_header->spare[0], sizeof (image_header->spare), "   spare[10] =\n");
2747
         printf ("   mountflags   = 0x%08x (%s %s %s %s)\n", image_header->mountflags, BINARY (((uint8_t *) &image_header->mountflags)[0]), BINARY (((uint8_t *) &image_header->mountflags)[1]), BINARY (((uint8_t *) &image_header->mountflags)[2]), BINARY (((uint8_t *) &image_header->mountflags)[3]));
2822
         printf ("   mountflags   = 0x%08x (%s %s %s %s)\n", image_header->mountflags, BINARY (((uint8_t *) &image_header->mountflags)[0]), BINARY (((uint8_t *) &image_header->mountflags)[1]), BINARY (((uint8_t *) &image_header->mountflags)[2]), BINARY (((uint8_t *) &image_header->mountflags)[3]));
2748
         printf ("   mountpoint   = \"%s\"\n", image_header->mountpoint);
2823
         printf ("   mountpoint   = \"%s\"\n", image_header->mountpoint);
2749
 
2824
 
2750
         // validate that the file can contain up to the image trailer
2825
         // validate that the file can contain up to the image trailer
2751
         if (current_offset + image_header->image_size > filesize)
2826
         if (current_offset + image_header->image_size > file.len)
2752
         {
2827
         {
2753
            printf ("WARNING: this IFS file is corrupted (image trailer extends past end of file)\n");
2828
            printf ("WARNING: this IFS file is corrupted (image trailer extends past end of file)\n");
2754
            goto endofdata;
2829
            goto endofdata;
2755
         }
2830
         }
2756
 
2831
 
Line 2763... Line 2838...
2763
 
2838
 
2764
         // locate the image trailer at the right offset
2839
         // locate the image trailer at the right offset
2765
         if (image_header->flags & IMAGE_FLAGS_TRAILER_V2)
2840
         if (image_header->flags & IMAGE_FLAGS_TRAILER_V2)
2766
         {
2841
         {
2767
            imagetrailer_offset = current_offset + image_header->image_size - sizeof (image_trailer_v2_t);
2842
            imagetrailer_offset = current_offset + image_header->image_size - sizeof (image_trailer_v2_t);
2768
            image_trailer_v2 = (image_trailer_v2_t *) &filedata[imagetrailer_offset];
2843
            image_trailer_v2 = (image_trailer_v2_t *) &file.bytes[imagetrailer_offset];
2769
         }
2844
         }
2770
         else // old V1 trailer
2845
         else // old V1 trailer
2771
         {
2846
         {
2772
            imagetrailer_offset = current_offset + image_header->image_size - sizeof (image_trailer_v1_t);
2847
            imagetrailer_offset = current_offset + image_header->image_size - sizeof (image_trailer_v1_t);
2773
            image_trailer_v1 = (image_trailer_v1_t *) &filedata[imagetrailer_offset];
2848
            image_trailer_v1 = (image_trailer_v1_t *) &file.bytes[imagetrailer_offset];
2774
         }
2849
         }
2775
 
2850
 
2776
         current_offset += sizeof (image_header_t); // jump over the image header and reach the first directory entry
2851
         current_offset += sizeof (image_header_t); // jump over the image header and reach the first directory entry
2777
 
2852
 
2778
         // there may be padding before the first directory entry
2853
         // there may be padding before the first directory entry
2779
         if (image_header->dir_offset - sizeof (image_header_t) > 0)
2854
         if (image_header->dir_offset - sizeof (image_header_t) > 0)
2780
            hex_printf (&filedata[current_offset], image_header->dir_offset - sizeof (image_header_t), "\n" "%zd padding bytes at offset 0x%zd (%zd):\n", image_header->dir_offset - sizeof (image_header_t), current_offset, current_offset);
2855
            hex_printf (&file.bytes[current_offset], image_header->dir_offset - sizeof (image_header_t), "\n" "%zd padding bytes at offset 0x%zd (%zd):\n", image_header->dir_offset - sizeof (image_header_t), current_offset, current_offset);
2781
         current_offset += image_header->dir_offset - sizeof (image_header_t); // padding was processed, jump over it
2856
         current_offset += image_header->dir_offset - sizeof (image_header_t); // padding was processed, jump over it
2782
 
2857
 
2783
         // dump all directory entries until the last one included
2858
         // dump all directory entries until the last one included
2784
         fsentries = NULL;
2859
         fsentries = NULL;
2785
         fsentry_count = 0;
2860
         fsentry_count = 0;
2786
         while (current_offset < imageheader_offset + image_header->hdr_dir_size)
2861
         while (current_offset < imageheader_offset + image_header->hdr_dir_size)
2787
         {
2862
         {
2788
            current_fsentry = (fsentry_t *) &filedata[current_offset];
2863
            current_fsentry = (fsentry_t *) &file.bytes[current_offset];
2789
 
2864
 
2790
            if (imageheader_offset + image_header->hdr_dir_size - current_offset < sizeof (current_fsentry->header))
2865
            if (imageheader_offset + image_header->hdr_dir_size - current_offset < sizeof (current_fsentry->header))
2791
               break; // end padding reached
2866
               break; // end padding reached
2792
 
2867
 
2793
            // stack up the filesystem entry pointers in an array while we read them
2868
            // stack up the filesystem entry pointers in an array while we read them
Line 2797... Line 2872...
2797
            fsentries[fsentry_count] = current_fsentry;
2872
            fsentries[fsentry_count] = current_fsentry;
2798
            fsentry_count++;
2873
            fsentry_count++;
2799
 
2874
 
2800
            printf ("\n");
2875
            printf ("\n");
2801
            printf ("Filesystem entry at offset 0x%zx (%zd) - last one at 0x%zd (%zd):\n", current_offset, current_offset, imageheader_offset + image_header->hdr_dir_size, imageheader_offset + image_header->hdr_dir_size);
2876
            printf ("Filesystem entry at offset 0x%zx (%zd) - last one at 0x%zd (%zd):\n", current_offset, current_offset, imageheader_offset + image_header->hdr_dir_size, imageheader_offset + image_header->hdr_dir_size);
2802
            printf ("   size           = 0x%04x (%d) - size of dirent - %s\n", current_fsentry->header.size, current_fsentry->header.size, ((current_fsentry->header.size > 0) && (current_offset + current_fsentry->header.size < filesize) ? "looks good" : "BAD"));
2877
            printf ("   size           = 0x%04x (%d) - size of dirent - %s\n", current_fsentry->header.size, current_fsentry->header.size, ((current_fsentry->header.size > 0) && (current_offset + current_fsentry->header.size < file.len) ? "looks good" : "BAD"));
2803
            printf ("   extattr_offset = 0x%04x (%d) - %s\n", current_fsentry->header.extattr_offset, current_fsentry->header.extattr_offset, (current_fsentry->header.extattr_offset == 0 ? "no extattr" : "has extattr"));
2878
            printf ("   extattr_offset = 0x%04x (%d) - %s\n", current_fsentry->header.extattr_offset, current_fsentry->header.extattr_offset, (current_fsentry->header.extattr_offset == 0 ? "no extattr" : "has extattr"));
2804
            printf ("   ino            = 0x%08x (%d) - inode number (%s%s%s%s)\n", current_fsentry->header.ino, current_fsentry->header.ino, (current_fsentry->header.ino & 0xE0000000 ? "is" : "nothing special"), (current_fsentry->header.ino & IFS_INO_PROCESSED_ELF ? " PROCESSED_ELF" : ""), (current_fsentry->header.ino & IFS_INO_RUNONCE_ELF ? " RUNONCE_ELF" : ""), (current_fsentry->header.ino & IFS_INO_BOOTSTRAP_EXE ? " BOOTSTRAP_EXE" : ""));
2879
            printf ("   ino            = 0x%08x (%d) - inode number (%s%s%s%s)\n", current_fsentry->header.ino, current_fsentry->header.ino, (current_fsentry->header.ino & 0xE0000000 ? "is" : "nothing special"), (current_fsentry->header.ino & IFS_INO_PROCESSED_ELF ? " PROCESSED_ELF" : ""), (current_fsentry->header.ino & IFS_INO_RUNONCE_ELF ? " RUNONCE_ELF" : ""), (current_fsentry->header.ino & IFS_INO_BOOTSTRAP_EXE ? " BOOTSTRAP_EXE" : ""));
2805
            printf ("   mode           = 0x%08x (%d) - %s (0%o), POSIX permissions 0%o\n", current_fsentry->header.mode, current_fsentry->header.mode, (S_ISDIR (current_fsentry->header.mode) ? "directory" : (S_ISREG (current_fsentry->header.mode) ? "file" : (S_ISLNK (current_fsentry->header.mode) ? "symlink" : "device"))), (current_fsentry->header.mode & 0xF000) >> 12, current_fsentry->header.mode & 0xFFF);
2880
            printf ("   mode           = 0x%08x (%d) - %s (0%o), POSIX permissions 0%o\n", current_fsentry->header.mode, current_fsentry->header.mode, (S_ISDIR (current_fsentry->header.mode) ? "directory" : (S_ISREG (current_fsentry->header.mode) ? "file" : (S_ISLNK (current_fsentry->header.mode) ? "symlink" : "device"))), (current_fsentry->header.mode & 0xF000) >> 12, current_fsentry->header.mode & 0xFFF);
2806
            printf ("   gid            = 0x%08x (%d) - owner group ID%s\n", current_fsentry->header.gid, current_fsentry->header.gid, (current_fsentry->header.gid == 0 ? " (root)" : ""));
2881
            printf ("   gid            = 0x%08x (%d) - owner group ID%s\n", current_fsentry->header.gid, current_fsentry->header.gid, (current_fsentry->header.gid == 0 ? " (root)" : ""));
2807
            printf ("   uid            = 0x%08x (%d) - owner user ID%s\n", current_fsentry->header.uid, current_fsentry->header.uid, (current_fsentry->header.uid == 0 ? " (root)" : ""));
2882
            printf ("   uid            = 0x%08x (%d) - owner user ID%s\n", current_fsentry->header.uid, current_fsentry->header.uid, (current_fsentry->header.uid == 0 ? " (root)" : ""));
Line 2809... Line 2884...
2809
            printf ("   mtime          = 0x%08x (%d) - POSIX timestamp: %s", current_fsentry->header.mtime, current_fsentry->header.mtime, asctime (localtime (&mtime))); // NOTE: asctime() provides the newline
2884
            printf ("   mtime          = 0x%08x (%d) - POSIX timestamp: %s", current_fsentry->header.mtime, current_fsentry->header.mtime, asctime (localtime (&mtime))); // NOTE: asctime() provides the newline
2810
            if (S_ISDIR (current_fsentry->header.mode))
2885
            if (S_ISDIR (current_fsentry->header.mode))
2811
               printf ("   [DIRECTORY] path = \"%s\"\n", (char *) &current_fsentry->u.dir.path); // convert from pointer to char array
2886
               printf ("   [DIRECTORY] path = \"%s\"\n", (char *) &current_fsentry->u.dir.path); // convert from pointer to char array
2812
            else if (S_ISREG (current_fsentry->header.mode))
2887
            else if (S_ISREG (current_fsentry->header.mode))
2813
            {
2888
            {
2814
               printf ("   [FILE] offset = 0x%08x (%d) - %s\n", current_fsentry->u.file.offset, current_fsentry->u.file.offset, (imageheader_offset + current_fsentry->u.file.offset < filesize ? "looks good" : "BAD (IFS file too short)"));
2889
               printf ("   [FILE] offset = 0x%08x (%d) - %s\n", current_fsentry->u.file.offset, current_fsentry->u.file.offset, (imageheader_offset + current_fsentry->u.file.offset < file.len ? "looks good" : "BAD (IFS file too short)"));
2815
               printf ("   [FILE] size   = 0x%08x (%d) - %s\n", current_fsentry->u.file.size, current_fsentry->u.file.size, (imageheader_offset + current_fsentry->u.file.offset + current_fsentry->u.file.size < filesize ? "looks good" : "BAD (IFS file too short)"));
2890
               printf ("   [FILE] size   = 0x%08x (%d) - %s\n", current_fsentry->u.file.size, current_fsentry->u.file.size, (imageheader_offset + current_fsentry->u.file.offset + current_fsentry->u.file.size < file.len ? "looks good" : "BAD (IFS file too short)"));
2816
               printf ("   [FILE] path   = \"%s\"\n", (char *) &current_fsentry->u.file.path); // convert from pointer to char array
2891
               printf ("   [FILE] path   = \"%s\"\n", (char *) &current_fsentry->u.file.path); // convert from pointer to char array
2817
            }
2892
            }
2818
            else if (S_ISLNK (current_fsentry->header.mode))
2893
            else if (S_ISLNK (current_fsentry->header.mode))
2819
            {
2894
            {
2820
               printf ("   [SYMLINK] sym_offset = 0x%04x (%d) - %s\n", current_fsentry->u.symlink.sym_offset, current_fsentry->u.symlink.sym_offset, (sizeof (current_fsentry->header) + 2 * sizeof (uint16_t) + current_fsentry->u.symlink.sym_offset <= current_fsentry->header.size ? "looks good" : "BAD (dirent too short)"));
2895
               printf ("   [SYMLINK] sym_offset = 0x%04x (%d) - %s\n", current_fsentry->u.symlink.sym_offset, current_fsentry->u.symlink.sym_offset, (sizeof (current_fsentry->header) + 2 * sizeof (uint16_t) + current_fsentry->u.symlink.sym_offset <= current_fsentry->header.size ? "looks good" : "BAD (dirent too short)"));
Line 2827... Line 2902...
2827
               printf ("   [DEVICE] dev  = 0x%08x (%d)\n", current_fsentry->u.device.dev, current_fsentry->u.device.dev);
2902
               printf ("   [DEVICE] dev  = 0x%08x (%d)\n", current_fsentry->u.device.dev, current_fsentry->u.device.dev);
2828
               printf ("   [DEVICE] rdev = 0x%08x (%d)\n", current_fsentry->u.device.rdev, current_fsentry->u.device.rdev);
2903
               printf ("   [DEVICE] rdev = 0x%08x (%d)\n", current_fsentry->u.device.rdev, current_fsentry->u.device.rdev);
2829
               printf ("   [DEVICE] path = \"%s\"\n", (char *) &current_fsentry->u.device.path); // convert from pointer to char array
2904
               printf ("   [DEVICE] path = \"%s\"\n", (char *) &current_fsentry->u.device.path); // convert from pointer to char array
2830
            }
2905
            }
2831
 
2906
 
2832
            if ((current_fsentry->header.size == 0) || (current_offset + current_fsentry->header.size >= filesize))
2907
            if ((current_fsentry->header.size == 0) || (current_offset + current_fsentry->header.size >= file.len))
2833
            {
2908
            {
2834
               printf ("WARNING: this IFS file is corrupted (the size of this directory entry is invalid)\n");
2909
               printf ("WARNING: this IFS file is corrupted (the size of this directory entry is invalid)\n");
2835
               goto endofdata;
2910
               goto endofdata;
2836
            }
2911
            }
2837
 
2912
 
2838
            current_offset += current_fsentry->header.size;
2913
            current_offset += current_fsentry->header.size;
2839
         }
2914
         }
2840
         if (imageheader_offset + image_header->hdr_dir_size < current_offset + sizeof (current_fsentry->header))
2915
         if (imageheader_offset + image_header->hdr_dir_size < current_offset + sizeof (current_fsentry->header))
2841
            hex_printf (&filedata[current_offset], imageheader_offset + image_header->hdr_dir_size - current_offset, "\n" "%zd padding bytes at offset 0x%zx (%zd):\n", imageheader_offset + image_header->hdr_dir_size - current_offset, current_offset, current_offset);
2916
            hex_printf (&file.bytes[current_offset], imageheader_offset + image_header->hdr_dir_size - current_offset, "\n" "%zd padding bytes at offset 0x%zx (%zd):\n", imageheader_offset + image_header->hdr_dir_size - current_offset, current_offset, current_offset);
2842
         current_offset += imageheader_offset + image_header->hdr_dir_size - current_offset; // padding was processed, jump over it
2917
         current_offset += imageheader_offset + image_header->hdr_dir_size - current_offset; // padding was processed, jump over it
2843
 
2918
 
2844
         // at this point we are past the directory entries; what is stored now, up to and until the image trailer, is the files' data
2919
         // at this point we are past the directory entries; what is stored now, up to and until the image trailer, is the files' data
2845
         if (fsentry_count > 0)
2920
         if (fsentry_count > 0)
2846
         {
2921
         {
Line 2862... Line 2937...
2862
               fsentry_index = nearest_index;
2937
               fsentry_index = nearest_index;
2863
               current_fsentry = fsentries[fsentry_index]; // quick access to closest fsentry
2938
               current_fsentry = fsentries[fsentry_index]; // quick access to closest fsentry
2864
 
2939
 
2865
               // there may be padding before the file data
2940
               // there may be padding before the file data
2866
               if (imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset > 0)
2941
               if (imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset > 0)
2867
                  hex_printf (&filedata[current_offset], imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset, "\n" "%zd padding bytes at offset 0x%zx (%zd):\n", imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset, current_offset, current_offset);
2942
                  hex_printf (&file.bytes[current_offset], imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset, "\n" "%zd padding bytes at offset 0x%zx (%zd):\n", imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset, current_offset, current_offset);
2868
               current_offset += imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset; // padding was processed, jump over it
2943
               current_offset += imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset; // padding was processed, jump over it
2869
 
2944
 
2870
               printf ("\n");
2945
               printf ("\n");
2871
               printf ("File data blob at offset 0x%zx (%zd):\n", current_offset, current_offset);
2946
               printf ("File data blob at offset 0x%zx (%zd):\n", current_offset, current_offset);
2872
               printf ("   corresponding dirent index: %zd/%zd\n", fsentry_index, fsentry_count);
2947
               printf ("   corresponding dirent index: %zd/%zd\n", fsentry_index, fsentry_count);
2873
               printf ("   corresponding inode 0x%08x (%d) -%s%s%s%s\n", current_fsentry->header.ino, current_fsentry->header.ino, (current_fsentry->header.ino & 0xE0000000 ? "" : " nothing special"), (current_fsentry->header.ino & IFS_INO_PROCESSED_ELF ? " PROCESSED_ELF" : ""), (current_fsentry->header.ino & IFS_INO_RUNONCE_ELF ? " RUNONCE_ELF" : ""), (current_fsentry->header.ino & IFS_INO_BOOTSTRAP_EXE ? " BOOTSTRAP_EXE" : ""));
2948
               printf ("   corresponding inode 0x%08x (%d) -%s%s%s%s\n", current_fsentry->header.ino, current_fsentry->header.ino, (current_fsentry->header.ino & 0xE0000000 ? "" : " nothing special"), (current_fsentry->header.ino & IFS_INO_PROCESSED_ELF ? " PROCESSED_ELF" : ""), (current_fsentry->header.ino & IFS_INO_RUNONCE_ELF ? " RUNONCE_ELF" : ""), (current_fsentry->header.ino & IFS_INO_BOOTSTRAP_EXE ? " BOOTSTRAP_EXE" : ""));
2874
               printf ("   corresponding path: \"%s\"\n", (char *) &current_fsentry->u.file.path); // convert from pointer to char array
2949
               printf ("   corresponding path: \"%s\"\n", (char *) &current_fsentry->u.file.path); // convert from pointer to char array
2875
               printf ("   size 0x%zx (%zd) bytes\n", (size_t) current_fsentry->u.file.size, (size_t) current_fsentry->u.file.size);
2950
               printf ("   size 0x%zx (%zd) bytes\n", (size_t) current_fsentry->u.file.size, (size_t) current_fsentry->u.file.size);
2876
               if (current_offset + 4 < filesize)
2951
               if (current_offset + 4 < file.len)
2877
                  hex_printf (&filedata[current_offset], current_fsentry->u.file.size, "   data:\n");
2952
                  hex_printf (&file.bytes[current_offset], current_fsentry->u.file.size, "   data:\n");
2878
               if (current_offset + current_fsentry->u.file.size < filesize)
2953
               if (current_offset + current_fsentry->u.file.size < file.len)
2879
                  printf ("   checksum %d\n", update_checksum (&filedata[current_offset], current_fsentry->u.file.size, is_foreign_endianness));
2954
                  printf ("   checksum %d\n", update_checksum (&file.bytes[current_offset], current_fsentry->u.file.size, is_foreign_endianness));
2880
               else
2955
               else
2881
               {
2956
               {
2882
                  printf ("WARNING: this IFS file is corrupted (the size of this file data extends past the IFS size)\n");
2957
                  printf ("WARNING: this IFS file is corrupted (the size of this file data extends past the IFS size)\n");
2883
                  goto endofdata;
2958
                  goto endofdata;
2884
               }
2959
               }
Line 2887... Line 2962...
2887
            }
2962
            }
2888
         }
2963
         }
2889
 
2964
 
2890
         // ad this point we're past the last file data, there may be padding before the image trailer
2965
         // ad this point we're past the last file data, there may be padding before the image trailer
2891
         if (imagetrailer_offset - current_offset > 0)
2966
         if (imagetrailer_offset - current_offset > 0)
2892
            hex_printf (&filedata[current_offset], imagetrailer_offset - current_offset, "\n" "%zd padding bytes at offset %zx (%zd):\n", imagetrailer_offset - current_offset, current_offset, current_offset);
2967
            hex_printf (&file.bytes[current_offset], imagetrailer_offset - current_offset, "\n" "%zd padding bytes at offset %zx (%zd):\n", imagetrailer_offset - current_offset, current_offset, current_offset);
2893
         current_offset += imagetrailer_offset - current_offset; // padding was processed, jump over it
2968
         current_offset += imagetrailer_offset - current_offset; // padding was processed, jump over it
2894
 
2969
 
2895
         printf ("\n");
2970
         printf ("\n");
2896
         printf ("Image trailer at offset 0x%zx (%zd) - version %d:\n", current_offset, current_offset, (image_header->flags & IMAGE_FLAGS_TRAILER_V2 ? 2 : 1));
2971
         printf ("Image trailer at offset 0x%zx (%zd) - version %d:\n", current_offset, current_offset, (image_header->flags & IMAGE_FLAGS_TRAILER_V2 ? 2 : 1));
2897
         if (image_header->flags & IMAGE_FLAGS_TRAILER_V2)
2972
         if (image_header->flags & IMAGE_FLAGS_TRAILER_V2)
Line 2922... Line 2997...
2922
 
2997
 
2923
      // else it has to be a boot blob, of which we don't know the size, except that it has to fit in 0xffff bytes and be immediately followed by a startup header
2998
      // else it has to be a boot blob, of which we don't know the size, except that it has to fit in 0xffff bytes and be immediately followed by a startup header
2924
      else
2999
      else
2925
      {
3000
      {
2926
         // so scan for the first startup header magic and version (which makes us 6 bytes to scan for, i.e. "\xeb\x7e\xff\x00" for the magic and "\x01\x00" (LSB) for the version 1)
3001
         // so scan for the first startup header magic and version (which makes us 6 bytes to scan for, i.e. "\xeb\x7e\xff\x00" for the magic and "\x01\x00" (LSB) for the version 1)
2927
         for (byte_index = current_offset; byte_index < filesize - 6; byte_index++)
3002
         for (byte_index = current_offset; byte_index < file.len - 6; byte_index++)
2928
            if (memcmp (&filedata[byte_index], "\xeb\x7e\xff\x00" "\x01\x00", 4 + 2) == 0)
3003
            if (memcmp (&file.bytes[byte_index], "\xeb\x7e\xff\x00" "\x01\x00", 4 + 2) == 0)
2929
               break; // stop as soon as we find it
3004
               break; // stop as soon as we find it
2930
 
3005
 
2931
         if (byte_index >= filesize - 6)
3006
         if (byte_index >= file.len - 6)
2932
            break; // if not found, stop scanning
3007
            break; // if not found, stop scanning
2933
 
3008
 
2934
         bootfile_blobsize = byte_index - current_offset;
3009
         bootfile_blobsize = byte_index - current_offset;
2935
         printf ("Boot blob at offset 0x%zx (%zd):\n", current_offset, current_offset);
3010
         printf ("Boot blob at offset 0x%zx (%zd):\n", current_offset, current_offset);
2936
         printf ("   size 0x%zx (%zd) bytes\n", bootfile_blobsize, bootfile_blobsize);
3011
         printf ("   size 0x%zx (%zd) bytes\n", bootfile_blobsize, bootfile_blobsize);
2937
         printf ("   checksum 0x%08x\n", update_checksum (&filedata[current_offset], bootfile_blobsize, false)); // NOTE: endianness is not known yet -- assume same
3012
         printf ("   checksum 0x%08x\n", update_checksum (&file.bytes[current_offset], bootfile_blobsize, false)); // NOTE: endianness is not known yet -- assume same
2938
 
3013
 
2939
         current_offset = byte_index; // now reach the next segment
3014
         current_offset = byte_index; // now reach the next segment
2940
      }
3015
      }
2941
   }
3016
   }
2942
 
3017
 
2943
endofdata:
3018
endofdata:
2944
   // at this point there's nothing left we're able to parse
3019
   // at this point there's nothing left we're able to parse
2945
   if (current_offset < filesize)
3020
   if (current_offset < file.len)
2946
   {
3021
   {
2947
      printf ("End of identifiable data reached.\n");
3022
      printf ("End of identifiable data reached.\n");
2948
      hex_printf (&filedata[current_offset], filesize - current_offset, "\n" "%zd extra bytes at offset %zx (%zd):\n", filesize - current_offset, current_offset, current_offset);
3023
      hex_printf (&file.bytes[current_offset], file.len - current_offset, "\n" "%zd extra bytes at offset %zx (%zd):\n", file.len - current_offset, current_offset, current_offset);
2949
   }
3024
   }
2950
 
3025
 
2951
   printf ("End of file reached at offset 0x%zx (%zd)\n", filesize, filesize);
3026
   printf ("End of file reached at offset 0x%zx (%zd)\n", file.len, file.len);
2952
   printf ("IFS dissecation complete.\n");
3027
   printf ("IFS dissecation complete.\n");
2953
   return (0);
3028
   return (0);
2954
}
3029
}