├── README.md ├── apache22-debian64.til ├── apache24-apr17-debian64.til ├── apache_all.h ├── gcc64.cfg ├── img └── before_after1.png ├── make_til.sh └── sizes.c /README.md: -------------------------------------------------------------------------------- 1 | # Creating TIL files for IDA 2 | 3 | ## Intro 4 | 5 | Creating a *Type Information Library* makes it easier to reverse engineer 6 | binaries by providing IDA with detailed and acurate information about types. 7 | 8 | Types include: 9 | 10 | * function prototypes 11 | * structures 12 | * enums 13 | 14 | The main point is that IDA will apply function prototypes to the imports 15 | and include the relevant data types in the database. 16 | 17 | 18 | ## Creating a TIL file for Apache 19 | 20 | As an example, we will create a TIL file which can help reversing Apache modules. 21 | 22 | 23 | Everything here will be done on a Debian Sid, amd64 from March 2021, but most of 24 | it will work on most Linux distros. 25 | 26 | 27 | ### Prerequisites 28 | 29 | We need the source code of the libraries we want to analyze. My target used 30 | Apache 2.2, so let's fetch it: 31 | 32 | ``` 33 | wget https://archive.apache.org/dist/httpd/httpd-2.2.34.tar.bz2 34 | wget https://archive.apache.org/dist/httpd/httpd-2.2.34.tar.bz2.asc 35 | curl https://downloads.apache.org/httpd/KEYS | gpg2 --import 36 | gpg2 --verify httpd-2.2.34.tar.bz2.asc httpd-2.2.34.tar.bz2 37 | ``` 38 | 39 | The archive contains things we want to include in our TIL: 40 | 41 | * the headers for writing modules 42 | * the Apache Runtime (apr) lib 43 | 44 | First, we need to do a `./configure` to have the right headers generated. 45 | Of course, this phase will need to reflect the configuration that was used 46 | by your target. 47 | 48 | In my case, the binary was compiled with `GCC: (GNU) 3.2.3 20030502 (Red Hat Linux 3.2.3-56)`, which 49 | is *ancient*. But in theory, there should not be real differences in ABI between a recent and old 50 | GCC compiler on Linux amd64, so let's proceed anyway. 51 | 52 | ## TIL 53 | 54 | ### Compiler config 55 | 56 | First, we need to get the right configuration for the compiler options in `tilib`: depending on 57 | the architecture and target ABI, the structures padding, type sizes, etc. will vary. 58 | 59 | This is the "documentation": 60 | 61 | ``` 62 | $ ./tilib -C? 63 | -C... specifies the compiler information 64 | It has the -Cx# form, where # - value, x is one of the following: 65 | c-compiler id, m-model, p-sizeof(near*), g-defalign (0/1/2/4/8/6 for16) 66 | b-sizeof(bool), e-sizeof(enum), i-sizeof(int), s-sizeof(short) 67 | l-sizeof(long), L-sizeof(longlong), R-explicit stack offsets 68 | v-calling convention, B-bitness (3 for 32 or 6 for 64), D-sizeof(long double) 69 | 8-4 byte alignment for 8byte scalars (__int64/double) inside structures (y/n) 70 | a-shorthand for cmpgbeislLvB8. The default is us40144248i3n 71 | Compiler ids: Pointer sizes: 72 | 0 or u: Unknown 1: sizeof(near*)=1, sizeof(far*)=2 73 | 1 or v: Visual C++ 2: sizeof(near*)=2, sizeof(far*)=4 74 | 2 or b: Borland C++ 4: sizeof(near*)=4, sizeof(far*)=6 75 | 3 or w: Watcom C++ 8: sizeof(near*)=8, sizeof(far*)=8 76 | 6 or g: GNU C++ Memory models: 77 | 7 or a: Visual Age C++ s: small (code=near, data=near) 78 | 8 or d: Delphi l: large (code=far, data=far) 79 | c: compact (code=near, data=far) 80 | m: medium (code=far, data=near) 81 | Calling conventions: 82 | i: invalid s: stdcall u: unknown (default) 83 | v: void p: pascall 84 | c: cdecl r: fastcall 85 | e: (...) t: thiscall 86 | For example, BCC small model v3.1: -Cabs2122224 87 | GNU C++: -Cags44444248u 88 | ``` 89 | 90 | 91 | As you can see, `-C` is *difficult* to master. Here's how to read the 92 | -`Cags44444` which you can find in tilib's `gcc.cfg`: 93 | 94 | ``` 95 | ; from GCC 32 config: 96 | ; -Cags44444 97 | ; cmpgbeislLvB8 (expansion for for "Ca") 98 | ; us40144248i3n (default) 99 | ; gs44444 100 | ; |||||||||||||_ 8bytes scalars alignment 101 | ; ||||||||||||__ bitness 102 | ; |||||||||||___ calling convention 103 | ; ||||||||||____ sizeof(longlong) 104 | ; |||||||||_____ sizeof(long) : 105 | ; ||||||||______ sizeof(short) : 4 106 | ; |||||||_______ sizeof(int) : 4 107 | ; ||||||________ sizeof(enum) : 4 108 | ; |||||_________ sizeof(bool) : 4 109 | ; ||||__________ defalign: 4 110 | ; |||___________ pointer size: 4 111 | ; ||____________ mem model: small 112 | ; |_____________ compiler: gcc 113 | ``` 114 | 115 | #### Creating our own config 116 | 117 | * Use `sizes.c` 118 | * `cp gcc.cfg gcc64.cfg` 119 | * Update `gcc64.cfg` 120 | 121 | **Note:** the (updated) `gcc64.cfg` was provided by Igor Skochinsky from Hex-Rays, I just added the comments. 122 | 123 | #### Building TIL steps 124 | 125 | First we need to make a top level header which includes everything: `apache_all.h`. 126 | 127 | Then, we will preprocess it using `gcc -E` to preprocess everything and facilitate 128 | the ingestion by `tilib`. 129 | 130 | Then we begin the loop of fixing errors and warnings. 131 | 132 | The most important hacks are: 133 | 134 | * Adding `#define __asm__(arg)` to our `apache_all.h` file, to "nop" inline asm 135 | * Adding `-D__extension__= \` to the `tilib` call, which will "nop" the unsupported `__extension__` keyword 136 | * Adding `"-D__builtin_va_list=void *"` which will work around the need for the internal definition of `va_list` 137 | * Add `-D__UNKNOWN_ATTR__=UNKNOWN_ATTR` in `gcc64.cfg` 138 | 139 | Of course the command line options could be included in the `.cfg` file. 140 | 141 | See `make_til.sh` for the final result. 142 | 143 | #### Fixing "opaque" structures 144 | 145 | Identify which structures have no "size" in the .til file: 146 | 147 | ``` 148 | $ tilib -l apache22-debian64.til | grep "FFFFFFFF struct" 149 | [...] 150 | FFFFFFFF struct ap_conf_vector_t; 151 | FFFFFFFF struct ap_filter_provider_t; 152 | FFFFFFFF struct apr_allocator_t; 153 | FFFFFFFF struct apr_bucket_alloc_t; 154 | [...] 155 | ``` 156 | 157 | some are opaque by "design", such as `ap_conf_vector_t`, others should be added 158 | in the `apache_all.h` file by copy pasting. 159 | 160 | 161 | # Result 162 | 163 | 164 | The TIL file should be put inside `til/pc` in IDA dir to be discovered. 165 | 166 | After loading the TIL file (Shift-F11, Insert), and defining the module export as `module`, note 167 | how all the Apache related imports are now in **bold**, with their types defined: 168 | ![Before / After](img/before_after1.png) 169 | -------------------------------------------------------------------------------- /apache22-debian64.til: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trou/apache-module-ida-til/d0454c3f913649299132db5e74a574f6b76e4f67/apache22-debian64.til -------------------------------------------------------------------------------- /apache24-apr17-debian64.til: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trou/apache-module-ida-til/d0454c3f913649299132db5e74a574f6b76e4f67/apache24-apr17-debian64.til -------------------------------------------------------------------------------- /apache_all.h: -------------------------------------------------------------------------------- 1 | 2 | /* Used to "nop" __asm__ macros which are not supported by 3 | * tilib 4 | */ 5 | #define __asm__(arg) 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #ifdef APACHE24 48 | #include 49 | #include 50 | #include 51 | #endif 52 | 53 | 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | 63 | /* ------------------------------------------------------------- 64 | * 65 | * COPY PASTE FROM APR HERE 66 | * 67 | */ 68 | 69 | 70 | /* apr_table (same for Apache 2.2 and apr 1.7 */ 71 | 72 | 73 | #define TABLE_HASH_SIZE 32 74 | #define TABLE_INDEX_MASK 0x1f 75 | #define TABLE_HASH(key) (TABLE_INDEX_MASK & *(unsigned char *)(key)) 76 | #define TABLE_INDEX_IS_INITIALIZED(t, i) ((t)->index_initialized & (1 << (i))) 77 | #define TABLE_SET_INDEX_INITIALIZED(t, i) ((t)->index_initialized |= (1 << (i))) 78 | 79 | // Damn structure is "opaque" 80 | 81 | struct apr_table_t { 82 | /* This has to be first to promote backwards compatibility with 83 | * older modules which cast a apr_table_t * to an apr_array_header_t *... 84 | * they should use the apr_table_elts() function for most of the 85 | * cases they do this for. 86 | */ 87 | /** The underlying array for the table */ 88 | apr_array_header_t a; 89 | #ifdef MAKE_TABLE_PROFILE 90 | /** Who created the array. */ 91 | void *creator; 92 | #endif 93 | /* An index to speed up table lookups. The way this works is: 94 | * - Hash the key into the index: 95 | * - index_first[TABLE_HASH(key)] is the offset within 96 | * the table of the first entry with that key 97 | * - index_last[TABLE_HASH(key)] is the offset within 98 | * the table of the last entry with that key 99 | * - If (and only if) there is no entry in the table whose 100 | * key hashes to index element i, then the i'th bit 101 | * of index_initialized will be zero. (Check this before 102 | * trying to use index_first[i] or index_last[i]!) 103 | */ 104 | apr_uint32_t index_initialized; 105 | int index_first[TABLE_HASH_SIZE]; 106 | int index_last[TABLE_HASH_SIZE]; 107 | }; 108 | 109 | typedef struct node_header_t { 110 | apr_size_t size; 111 | apr_bucket_alloc_t *alloc; 112 | apr_memnode_t *memnode; 113 | struct node_header_t *next; 114 | } node_header_t; 115 | 116 | struct apr_bucket_alloc_t { 117 | apr_pool_t *pool; 118 | apr_allocator_t *allocator; 119 | node_header_t *freelist; 120 | apr_memnode_t *blocks; 121 | }; 122 | 123 | struct cleanup_t { 124 | struct cleanup_t *next; 125 | const void *data; 126 | apr_status_t (*plain_cleanup_fn)(void *data); 127 | apr_status_t (*child_cleanup_fn)(void *data); 128 | }; 129 | 130 | #ifndef APACHE24 131 | 132 | struct ap_filter_provider_t { 133 | /** How to match this provider to filter dispatch criterion */ 134 | enum { 135 | STRING_MATCH, 136 | STRING_CONTAINS, 137 | REGEX_MATCH, 138 | INT_EQ, 139 | INT_LT, 140 | INT_LE, 141 | INT_GT, 142 | INT_GE, 143 | DEFINED 144 | } match_type; 145 | 146 | /** negation on match_type */ 147 | int not; 148 | 149 | /** The dispatch match itself - union member depends on match_type */ 150 | union { 151 | const char *string; 152 | ap_regex_t *regex; 153 | int number; 154 | } match; 155 | 156 | /** The filter that implements this provider */ 157 | ap_filter_rec_t *frec; 158 | 159 | /** The next provider in the list */ 160 | ap_filter_provider_t *next; 161 | 162 | /** Dispatch criteria for filter providers */ 163 | enum { 164 | HANDLER, 165 | REQUEST_HEADERS, 166 | RESPONSE_HEADERS, 167 | SUBPROCESS_ENV, 168 | CONTENT_TYPE 169 | } dispatch; 170 | 171 | /** Match value for filter providers */ 172 | const char* value; 173 | }; 174 | 175 | #define MAX_INDEX 20 176 | 177 | struct apr_allocator_t { 178 | /** largest used index into free[], always < MAX_INDEX */ 179 | apr_uint32_t max_index; 180 | /** Total size (in BOUNDARY_SIZE multiples) of unused memory before 181 | * blocks are given back. @see apr_allocator_max_free_set(). 182 | * @note Initialized to APR_ALLOCATOR_MAX_FREE_UNLIMITED, 183 | * which means to never give back blocks. 184 | */ 185 | apr_uint32_t max_free_index; 186 | /** 187 | * Memory size (in BOUNDARY_SIZE multiples) that currently must be freed 188 | * before blocks are given back. Range: 0..max_free_index 189 | */ 190 | apr_uint32_t current_free_index; 191 | #if APR_HAS_THREADS 192 | apr_thread_mutex_t *mutex; 193 | #endif /* APR_HAS_THREADS */ 194 | apr_pool_t *owner; 195 | /** 196 | * Lists of free nodes. Slot 0 is used for oversized nodes, 197 | * and the slots 1..MAX_INDEX-1 contain nodes of sizes 198 | * (i+1) * BOUNDARY_SIZE. Example for BOUNDARY_INDEX == 12: 199 | * slot 0: nodes larger than 81920 200 | * slot 1: size 8192 201 | * slot 2: size 12288 202 | * ... 203 | * slot 19: size 81920 204 | */ 205 | apr_memnode_t *free[MAX_INDEX]; 206 | }; 207 | 208 | 209 | struct apr_pool_t { 210 | apr_pool_t *parent; 211 | apr_pool_t *child; 212 | apr_pool_t *sibling; 213 | apr_pool_t **ref; 214 | cleanup_t *cleanups; 215 | cleanup_t *free_cleanups; 216 | apr_allocator_t *allocator; 217 | struct process_chain *subprocesses; 218 | apr_abortfunc_t abort_fn; 219 | apr_hash_t *user_data; 220 | const char *tag; 221 | 222 | #if !APR_POOL_DEBUG 223 | apr_memnode_t *active; 224 | apr_memnode_t *self; /* The node containing the pool itself */ 225 | char *self_first_avail; 226 | 227 | #else /* APR_POOL_DEBUG */ 228 | apr_pool_t *joined; /* the caller has guaranteed that this pool 229 | * will survive as long as ->joined */ 230 | debug_node_t *nodes; 231 | const char *file_line; 232 | apr_uint32_t creation_flags; 233 | unsigned int stat_alloc; 234 | unsigned int stat_total_alloc; 235 | unsigned int stat_clear; 236 | #if APR_HAS_THREADS 237 | apr_os_thread_t owner; 238 | apr_thread_mutex_t *mutex; 239 | #endif /* APR_HAS_THREADS */ 240 | #endif /* APR_POOL_DEBUG */ 241 | #ifdef NETWARE 242 | apr_os_proc_t owner_proc; 243 | #endif /* defined(NETWARE) */ 244 | cleanup_t *pre_cleanups; 245 | }; 246 | #else /* Apache 2.4 */ 247 | struct ap_filter_provider_t { 248 | ap_expr_info_t *expr; 249 | const char **types; 250 | 251 | /** The filter that implements this provider */ 252 | ap_filter_rec_t *frec; 253 | 254 | /** The next provider in the list */ 255 | ap_filter_provider_t *next; 256 | }; 257 | 258 | #define MAX_INDEX 20 259 | struct apr_allocator_t { 260 | /** largest used index into free[], always < MAX_INDEX */ 261 | apr_size_t max_index; 262 | /** Total size (in BOUNDARY_SIZE multiples) of unused memory before 263 | * blocks are given back. @see apr_allocator_max_free_set(). 264 | * @note Initialized to APR_ALLOCATOR_MAX_FREE_UNLIMITED, 265 | * which means to never give back blocks. 266 | */ 267 | apr_size_t max_free_index; 268 | /** 269 | * Memory size (in BOUNDARY_SIZE multiples) that currently must be freed 270 | * before blocks are given back. Range: 0..max_free_index 271 | */ 272 | apr_size_t current_free_index; 273 | #if APR_HAS_THREADS 274 | apr_thread_mutex_t *mutex; 275 | #endif /* APR_HAS_THREADS */ 276 | apr_pool_t *owner; 277 | /** 278 | * Lists of free nodes. Slot 0 is used for oversized nodes, 279 | * and the slots 1..MAX_INDEX-1 contain nodes of sizes 280 | * (i+1) * BOUNDARY_SIZE. Example for BOUNDARY_INDEX == 12: 281 | * slot 0: nodes larger than 81920 282 | * slot 1: size 8192 283 | * slot 2: size 12288 284 | * ... 285 | * slot 19: size 81920 286 | */ 287 | apr_memnode_t *free[MAX_INDEX]; 288 | }; 289 | struct apr_pool_t { 290 | apr_pool_t *parent; 291 | apr_pool_t *child; 292 | apr_pool_t *sibling; 293 | apr_pool_t **ref; 294 | cleanup_t *cleanups; 295 | cleanup_t *free_cleanups; 296 | apr_allocator_t *allocator; 297 | struct process_chain *subprocesses; 298 | apr_abortfunc_t abort_fn; 299 | apr_hash_t *user_data; 300 | const char *tag; 301 | 302 | #if !APR_POOL_DEBUG 303 | apr_memnode_t *active; 304 | apr_memnode_t *self; /* The node containing the pool itself */ 305 | char *self_first_avail; 306 | 307 | #else /* APR_POOL_DEBUG */ 308 | apr_pool_t *joined; /* the caller has guaranteed that this pool 309 | * will survive as long as ->joined */ 310 | debug_node_t *nodes; 311 | const char *file_line; 312 | apr_uint32_t creation_flags; 313 | unsigned int stat_alloc; 314 | unsigned int stat_total_alloc; 315 | unsigned int stat_clear; 316 | #if APR_HAS_THREADS 317 | apr_os_thread_t owner; 318 | apr_thread_mutex_t *mutex; 319 | #endif /* APR_HAS_THREADS */ 320 | #endif /* APR_POOL_DEBUG */ 321 | #ifdef NETWARE 322 | apr_os_proc_t owner_proc; 323 | #endif /* defined(NETWARE) */ 324 | cleanup_t *pre_cleanups; 325 | #if APR_POOL_CONCURRENCY_CHECK 326 | 327 | #define IDLE 0 328 | #define IN_USE 1 329 | #define DESTROYED 2 330 | volatile apr_uint32_t in_use; 331 | apr_os_thread_t in_use_by; 332 | #endif /* APR_POOL_CONCURRENCY_CHECK */ 333 | }; 334 | 335 | struct ap_filter_provider_t { 336 | ap_expr_info_t *expr; 337 | const char **types; 338 | 339 | /** The filter that implements this provider */ 340 | ap_filter_rec_t *frec; 341 | 342 | /** The next provider in the list */ 343 | ap_filter_provider_t *next; 344 | }; 345 | #endif 346 | 347 | -------------------------------------------------------------------------------- /gcc64.cfg: -------------------------------------------------------------------------------- 1 | ; from GCC 32 config: 2 | ; -Cags44444 3 | ; cmpgbeislLvB8 (shortcut for "a") 4 | ; us40144248i3n (default) 5 | ; gs44444 6 | ; |||||||||||||_ 8bytes scalars alignment 7 | ; ||||||||||||__ bitness 8 | ; |||||||||||___ calling convention 9 | ; ||||||||||____ sizeof(longlong) 10 | ; |||||||||_____ sizeof(long) : 11 | ; ||||||||______ sizeof(short) : 4 12 | ; |||||||_______ sizeof(int) : 4 13 | ; ||||||________ sizeof(enum) : 4 14 | ; |||||_________ sizeof(bool) : 4 15 | ; ||||__________ defalign: 4 16 | ; |||___________ pointer size: 4 17 | ; ||____________ mem model: small 18 | ; |_____________ compiler: gcc 19 | 20 | ; for GCC 64 21 | ; cmpgbeislLvB8 (shortcut for "a") 22 | ; us40144248i3n (default) 23 | ; gs80144288u6 (sent by Igor) 24 | ; gs84144288 25 | ; |||||||||||||_ 8bytes scalars alignment 26 | ; ||||||||||||__ bitness 27 | ; |||||||||||___ calling convention 28 | ; ||||||||||____ sizeof(longlong) 29 | ; |||||||||_____ sizeof(long) : 30 | ; ||||||||______ sizeof(short) : 4 31 | ; |||||||_______ sizeof(int) : 4 32 | ; ||||||________ sizeof(enum) : 4 33 | ; |||||_________ sizeof(bool) : 4 34 | ; ||||__________ defalign: 4 35 | ; |||___________ pointer size: 8 36 | ; ||____________ mem model: small 37 | ; |_____________ compiler: gcc 38 | 39 | -Cags80144288u6 40 | ; cmpgbeislLvB 41 | -Isuse10_2 42 | -Igcc4_8_2 43 | 44 | -D__inline=inline 45 | -D__inline__=inline 46 | -D__signed__=signed 47 | -D__x86_64=1 48 | -D__x86_64__=1 49 | -D__amd64__=1 50 | -D__LP64__=1 51 | ; to accept C identifiers 'class', 'private', 'new' 52 | -Dclass=c_class 53 | -Dprivate=c_private 54 | -Dnew=_new 55 | 56 | -D__packed__=packed 57 | -D__transparent_union__=transparent_union 58 | -D__malloc__=malloc 59 | -D__alloc_size__=alloc_size 60 | -D__always_inline__=always_inline 61 | -D__vector_size__=vector_size 62 | -D__weak__=weak 63 | -D__noreturn__=noreturn 64 | -D__aligned__=aligned 65 | -D__attribute=__attribute__ 66 | -D__nonnull__=nonnull 67 | -D__nothrow__=nothrow 68 | -D__warn_unused_result__=warn_unused_result 69 | -D__mode__=mode 70 | -D__deprecated__=deprecated 71 | -D__pure__=pure 72 | 73 | -D__cleanup_fct_attribute= 74 | 75 | -D_K_SS_ALIGNSIZE=8 76 | 77 | -D__INT_MAX__=2147483647 78 | 79 | -D__GNUC__=4 80 | -D_GNU_SOURCE 81 | -D__unix__ 82 | -D__STDC__ 83 | -D_HAVE_INT64 84 | -D__GLIBC_HAVE_LONG_LONG 85 | 86 | -DHAVE_BOOL 87 | 88 | -Dlinux 89 | -------------------------------------------------------------------------------- /img/before_after1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trou/apache-module-ida-til/d0454c3f913649299132db5e74a574f6b76e4f67/img/before_after1.png -------------------------------------------------------------------------------- /make_til.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export NLSPATH=$HOME/bin/ida76 4 | TILIB=/home/raph/tools/reverse/IDA/v7.6/tools/tilib76/ 5 | 6 | ALL_HDR=apache2.2-all.h 7 | HTTPD=httpd-2.2.34 8 | gcc -I$HTTPD/os/unix/ -I$HTTPD/include/ -I$HTTPD/srclib/apr/include/ -I$HTTPD/srclib/apr-util/include/ -I$HTTPD/modules/filters/ -E apache_all.h | grep -v "^# " > $ALL_HDR 9 | 10 | $TILIB/linux/tilib64 @gcc64.cfg \ 11 | -c \ 12 | "-b$NLSPATH/til/pc/gnulnx_x64.til" \ 13 | "-h$ALL_HDR" \ 14 | -D__extension__= \ 15 | "-D__builtin_va_list=void *" \ 16 | -t"Apache 2.2 - Linux 64bit" \ 17 | apache22-debian64.til | grep -v "Unrecognized attribute" 18 | 19 | ALL_HDR=apache2.4-all.h 20 | gcc -DAPACHE24 -Ihttpd-2.4.46/os/unix/ -Ihttpd-2.4.46/include/ -Ihttpd-2.4.46/srclib/apr/include/ -Ihttpd-2.4.46/srclib/apr-util/include/ -E apache_all.h | grep -v "^# " > $ALL_HDR 21 | 22 | $TILIB/linux/tilib64 @gcc64.cfg \ 23 | -c \ 24 | "-b$NLSPATH/til/pc/gnulnx_x64.til" \ 25 | "-h$ALL_HDR" \ 26 | -D__extension__= \ 27 | "-D__builtin_va_list=void *" \ 28 | apache24-apr17-debian64.til | grep -v "Unrecognized attribute" 29 | 30 | cp apache24-apr17-debian64.til apache22-debian64.til "$NLSPATH/til/" 31 | -------------------------------------------------------------------------------- /sizes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct test { 5 | char a; 6 | int b; 7 | long c; 8 | long long d; 9 | }; 10 | enum testenum { 11 | toto = 1 12 | }; 13 | 14 | int main() 15 | { 16 | struct test a; 17 | enum testenum en; 18 | 19 | printf("sizeof(void *) (%lu)\n", sizeof(void *)); 20 | printf("sizeof(char) (%lu)\n", sizeof(a.a)); 21 | printf("int-char align (%lu)\n",(char *)&a.b-(char *)&a.a); 22 | printf("sizeof(int) (%lu)\n", sizeof(a.b)); 23 | printf("long-int align (%lu)\n",(char *)&a.c-(char *)&a.b); 24 | printf("sizeof(long) (%lu)\n", sizeof(a.c)); 25 | printf("long long-long align (%lu)\n",(char *)&a.d-(char *)&a.c); 26 | printf("sizeof(long long) (%lu)\n", sizeof(a.d)); 27 | printf("sizeof(bool) %lu\n", sizeof(bool)); 28 | printf("sizeof(short) %lu\n", sizeof(short)); 29 | printf("sizeof(enum) %lu\n", sizeof(en)); 30 | } 31 | 32 | 33 | --------------------------------------------------------------------------------