Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/tools/winedump/ne.c
8729 views
1
/*
2
* Dumping of NE binaries
3
*
4
* Copyright 2002 Alexandre Julliard
5
*
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19
*/
20
21
#include "config.h"
22
23
#include <stdarg.h>
24
#include <stdio.h>
25
#include <fcntl.h>
26
27
#include "windef.h"
28
#include "winbase.h"
29
#include "verrsrc.h"
30
#include "winedump.h"
31
32
struct ne_segtable_entry
33
{
34
WORD seg_data_offset; /* Sector offset of segment data */
35
WORD seg_data_length; /* Length of segment data */
36
WORD seg_flags; /* Flags associated with this segment */
37
WORD min_alloc; /* Minimum allocation size for this */
38
};
39
40
struct relocation_entry
41
{
42
BYTE address_type; /* Relocation address type */
43
BYTE relocation_type; /* Relocation type */
44
WORD offset; /* Offset in segment to fixup */
45
WORD target1; /* Target specification */
46
WORD target2; /* Target specification */
47
};
48
49
typedef struct
50
{
51
WORD offset;
52
WORD length;
53
WORD flags;
54
WORD id;
55
WORD handle;
56
WORD usage;
57
} NE_NAMEINFO;
58
59
typedef struct
60
{
61
WORD type_id;
62
WORD count;
63
DWORD resloader;
64
} NE_TYPEINFO;
65
66
#define NE_RADDR_LOWBYTE 0
67
#define NE_RADDR_SELECTOR 2
68
#define NE_RADDR_POINTER32 3
69
#define NE_RADDR_OFFSET16 5
70
#define NE_RADDR_POINTER48 11
71
#define NE_RADDR_OFFSET32 13
72
73
#define NE_RELTYPE_INTERNAL 0
74
#define NE_RELTYPE_ORDINAL 1
75
#define NE_RELTYPE_NAME 2
76
#define NE_RELTYPE_OSFIXUP 3
77
#define NE_RELFLAG_ADDITIVE 4
78
79
#define NE_SEGFLAGS_DATA 0x0001
80
#define NE_SEGFLAGS_ALLOCATED 0x0002
81
#define NE_SEGFLAGS_LOADED 0x0004
82
#define NE_SEGFLAGS_ITERATED 0x0008
83
#define NE_SEGFLAGS_MOVEABLE 0x0010
84
#define NE_SEGFLAGS_SHAREABLE 0x0020
85
#define NE_SEGFLAGS_PRELOAD 0x0040
86
#define NE_SEGFLAGS_EXECUTEONLY 0x0080
87
#define NE_SEGFLAGS_READONLY 0x0080
88
#define NE_SEGFLAGS_RELOC_DATA 0x0100
89
#define NE_SEGFLAGS_SELFLOAD 0x0800
90
#define NE_SEGFLAGS_DISCARDABLE 0x1000
91
#define NE_SEGFLAGS_32BIT 0x2000
92
93
#define NE_RSCTYPE_CURSOR 0x8001
94
#define NE_RSCTYPE_BITMAP 0x8002
95
#define NE_RSCTYPE_ICON 0x8003
96
#define NE_RSCTYPE_MENU 0x8004
97
#define NE_RSCTYPE_DIALOG 0x8005
98
#define NE_RSCTYPE_STRING 0x8006
99
#define NE_RSCTYPE_FONTDIR 0x8007
100
#define NE_RSCTYPE_FONT 0x8008
101
#define NE_RSCTYPE_ACCELERATOR 0x8009
102
#define NE_RSCTYPE_RCDATA 0x800a
103
#define NE_RSCTYPE_GROUP_CURSOR 0x800c
104
#define NE_RSCTYPE_GROUP_ICON 0x800e
105
#define NE_RSCTYPE_VERSION 0x8010
106
#define NE_RSCTYPE_SCALABLE_FONTPATH 0x80cc
107
108
static inline WORD get_word( const BYTE *ptr )
109
{
110
return ptr[0] | (ptr[1] << 8);
111
}
112
113
static void dump_ne_header( const IMAGE_OS2_HEADER *ne )
114
{
115
printf( "File header:\n" );
116
printf( "Linker version: %d.%d\n", ne->ne_ver, ne->ne_rev );
117
printf( "Entry table: %x len %d\n", ne->ne_enttab, ne->ne_cbenttab );
118
printf( "Checksum: %08x\n", (UINT)ne->ne_crc );
119
printf( "Flags: %04x\n", ne->ne_flags );
120
printf( "Auto data segment: %x\n", ne->ne_autodata );
121
printf( "Heap size: %d bytes\n", ne->ne_heap );
122
printf( "Stack size: %d bytes\n", ne->ne_stack );
123
printf( "Stack pointer: %x:%04x\n", HIWORD(ne->ne_sssp), LOWORD(ne->ne_sssp) );
124
printf( "Entry point: %x:%04x\n", HIWORD(ne->ne_csip), LOWORD(ne->ne_csip) );
125
printf( "Number of segments: %d\n", ne->ne_cseg );
126
printf( "Number of modrefs: %d\n", ne->ne_cmod );
127
printf( "Segment table: %x\n", ne->ne_segtab );
128
printf( "Resource table: %x\n", ne->ne_rsrctab );
129
printf( "Resident name table: %x\n", ne->ne_restab );
130
printf( "Module table: %x\n", ne->ne_modtab );
131
printf( "Import table: %x\n", ne->ne_imptab );
132
printf( "Non-resident table: %x\n", (UINT)ne->ne_nrestab );
133
printf( "Exe type: %x\n", ne->ne_exetyp );
134
printf( "Other flags: %x\n", ne->ne_flagsothers );
135
printf( "Fast load area: %x-%x\n", ne->ne_pretthunks << ne->ne_align,
136
(ne->ne_pretthunks+ne->ne_psegrefbytes) << ne->ne_align );
137
printf( "Expected version: %d.%d\n", HIBYTE(ne->ne_expver), LOBYTE(ne->ne_expver) );
138
}
139
140
static void dump_ne_names( const IMAGE_OS2_HEADER *ne )
141
{
142
const unsigned char *pstr = (const unsigned char *)ne + ne->ne_restab;
143
144
printf( "\nResident name table:\n" );
145
while (*pstr)
146
{
147
printf( " %4d: %*.*s\n", get_word(pstr + *pstr + 1), *pstr, *pstr, pstr + 1 );
148
pstr += *pstr + 1 + sizeof(WORD);
149
}
150
if (ne->ne_cbnrestab)
151
{
152
unsigned int pos = ne->ne_nrestab;
153
printf( "\nNon-resident name table:\n" );
154
while ((pstr = PRD(pos, 0)) && *pstr)
155
{
156
printf( " %4d: %*.*s\n", get_word(pstr + *pstr + 1), *pstr, *pstr, pstr + 1 );
157
pos += *pstr + 1 + sizeof(WORD);
158
}
159
}
160
}
161
162
static const char *get_resource_type( WORD id )
163
{
164
static char buffer[5];
165
switch(id)
166
{
167
case NE_RSCTYPE_CURSOR: return "CURSOR";
168
case NE_RSCTYPE_BITMAP: return "BITMAP";
169
case NE_RSCTYPE_ICON: return "ICON";
170
case NE_RSCTYPE_MENU: return "MENU";
171
case NE_RSCTYPE_DIALOG: return "DIALOG";
172
case NE_RSCTYPE_STRING: return "STRING";
173
case NE_RSCTYPE_FONTDIR: return "FONTDIR";
174
case NE_RSCTYPE_FONT: return "FONT";
175
case NE_RSCTYPE_ACCELERATOR: return "ACCELERATOR";
176
case NE_RSCTYPE_RCDATA: return "RCDATA";
177
case NE_RSCTYPE_GROUP_CURSOR: return "CURSOR_GROUP";
178
case NE_RSCTYPE_GROUP_ICON: return "ICON_GROUP";
179
case NE_RSCTYPE_VERSION: return "VERSION";
180
default:
181
sprintf( buffer, "%04x", id );
182
return buffer;
183
}
184
}
185
186
/* dump data for a STRING resource */
187
static void dump_string_data( const char *ptr, unsigned int size, unsigned int id, const char *prefix )
188
{
189
int i;
190
191
for (i = 0; i < 16 && size; i++)
192
{
193
unsigned int len = (unsigned char)*ptr++;
194
195
if (len >= size)
196
{
197
len = size;
198
size = 0;
199
}
200
else size -= len + 1;
201
202
if (len)
203
{
204
printf( "%s%04x \"", prefix, (id - 1) * 16 + i );
205
dump_strA( ptr, len );
206
printf( "\"\n" );
207
ptr += len;
208
}
209
}
210
}
211
212
struct version_info
213
{
214
WORD len;
215
WORD val_len;
216
char key[1];
217
};
218
#define GET_VALUE(info) ((void *)((char *)info + ((offsetof(struct version_info, key[strlen(info->key) + 1]) + 3) & ~3)))
219
#define GET_CHILD(info) ((void *)((char *)GET_VALUE(info) + ((info->val_len + 3) & ~3)))
220
#define GET_NEXT(info) ((void *)((char *)info + ((info->len + 3) & ~3)))
221
222
static void dump_version_children( const struct version_info *info, const char *prefix, int indent )
223
{
224
const struct version_info *next, *child = GET_CHILD( info );
225
226
for ( ; (char *)child < (char *)info + info->len; child = next)
227
{
228
next = GET_NEXT( child );
229
printf( "%s%*s", prefix, indent * 2, "" );
230
if (child->val_len || GET_VALUE( child ) == next)
231
{
232
printf( "VALUE \"" );
233
dump_strA( child->key, strlen(child->key) );
234
printf( "\", \"" );
235
dump_strA( GET_VALUE(child), child->val_len );
236
printf( "\"\n" );
237
}
238
else
239
{
240
printf( "BLOCK \"" );
241
dump_strA( child->key, strlen(child->key) );
242
printf( "\"\n" );
243
}
244
dump_version_children( child, prefix, indent + 1 );
245
}
246
}
247
248
/* dump data for a VERSION resource */
249
static void dump_version_data( const void *ptr, unsigned int size, const char *prefix )
250
{
251
const struct version_info *info = ptr;
252
const VS_FIXEDFILEINFO *fileinfo = GET_VALUE( info );
253
254
printf( "%sSIGNATURE %08x\n", prefix, (UINT)fileinfo->dwSignature );
255
printf( "%sVERSION %u.%u\n", prefix,
256
HIWORD(fileinfo->dwStrucVersion), LOWORD(fileinfo->dwStrucVersion) );
257
printf( "%sFILEVERSION %u.%u.%u.%u\n", prefix,
258
HIWORD(fileinfo->dwFileVersionMS), LOWORD(fileinfo->dwFileVersionMS),
259
HIWORD(fileinfo->dwFileVersionLS), LOWORD(fileinfo->dwFileVersionLS) );
260
printf( "%sPRODUCTVERSION %u.%u.%u.%u\n", prefix,
261
HIWORD(fileinfo->dwProductVersionMS), LOWORD(fileinfo->dwProductVersionMS),
262
HIWORD(fileinfo->dwProductVersionLS), LOWORD(fileinfo->dwProductVersionLS) );
263
printf( "%sFILEFLAGSMASK %08x\n", prefix, (UINT)fileinfo->dwFileFlagsMask );
264
printf( "%sFILEFLAGS %08x\n", prefix, (UINT)fileinfo->dwFileFlags );
265
266
switch (fileinfo->dwFileOS)
267
{
268
#define CASE(x) case x: printf( "%sFILEOS %s\n", prefix, #x ); break
269
CASE(VOS_UNKNOWN);
270
CASE(VOS_DOS_WINDOWS16);
271
CASE(VOS_DOS_WINDOWS32);
272
CASE(VOS_OS216_PM16);
273
CASE(VOS_OS232_PM32);
274
CASE(VOS_NT_WINDOWS32);
275
#undef CASE
276
default:
277
printf( "%sFILEOS %u.%u\n", prefix,
278
(WORD)(fileinfo->dwFileOS >> 16), (WORD)fileinfo->dwFileOS );
279
break;
280
}
281
282
switch (fileinfo->dwFileType)
283
{
284
#define CASE(x) case x: printf( "%sFILETYPE %s\n", prefix, #x ); break
285
CASE(VFT_UNKNOWN);
286
CASE(VFT_APP);
287
CASE(VFT_DLL);
288
CASE(VFT_DRV);
289
CASE(VFT_FONT);
290
CASE(VFT_VXD);
291
CASE(VFT_STATIC_LIB);
292
#undef CASE
293
default:
294
printf( "%sFILETYPE %08x\n", prefix, (UINT)fileinfo->dwFileType );
295
break;
296
}
297
298
switch (((ULONGLONG)fileinfo->dwFileType << 32) + fileinfo->dwFileSubtype)
299
{
300
#define CASE(t,x) case (((ULONGLONG)t << 32) + x): printf( "%sFILESUBTYPE %s\n", prefix, #x ); break
301
CASE(VFT_DRV, VFT2_UNKNOWN);
302
CASE(VFT_DRV, VFT2_DRV_PRINTER);
303
CASE(VFT_DRV, VFT2_DRV_KEYBOARD);
304
CASE(VFT_DRV, VFT2_DRV_LANGUAGE);
305
CASE(VFT_DRV, VFT2_DRV_DISPLAY);
306
CASE(VFT_DRV, VFT2_DRV_MOUSE);
307
CASE(VFT_DRV, VFT2_DRV_NETWORK);
308
CASE(VFT_DRV, VFT2_DRV_SYSTEM);
309
CASE(VFT_DRV, VFT2_DRV_INSTALLABLE);
310
CASE(VFT_DRV, VFT2_DRV_SOUND);
311
CASE(VFT_DRV, VFT2_DRV_COMM);
312
CASE(VFT_DRV, VFT2_DRV_INPUTMETHOD);
313
CASE(VFT_DRV, VFT2_DRV_VERSIONED_PRINTER);
314
CASE(VFT_FONT, VFT2_FONT_RASTER);
315
CASE(VFT_FONT, VFT2_FONT_VECTOR);
316
CASE(VFT_FONT, VFT2_FONT_TRUETYPE);
317
#undef CASE
318
default:
319
printf( "%sFILESUBTYPE %08x\n", prefix, (UINT)fileinfo->dwFileSubtype );
320
break;
321
}
322
323
printf( "%sFILEDATE %08x.%08x\n", prefix,
324
(UINT)fileinfo->dwFileDateMS, (UINT)fileinfo->dwFileDateLS );
325
dump_version_children( info, prefix, 0 );
326
}
327
328
static void dump_ne_resources( const IMAGE_OS2_HEADER *ne )
329
{
330
const NE_NAMEINFO *name;
331
const void *res_ptr = (const char *)ne + ne->ne_rsrctab;
332
WORD size_shift = get_word(res_ptr);
333
const NE_TYPEINFO *info = (const NE_TYPEINFO *)((const WORD *)res_ptr + 1);
334
int count;
335
336
printf( "\nResources:\n" );
337
while (info->type_id != 0 && (const char *)info < (const char *)ne + ne->ne_restab)
338
{
339
name = (const NE_NAMEINFO *)(info + 1);
340
for (count = info->count; count > 0; count--, name++)
341
{
342
if (info->type_id & 0x8000) printf( " %s", get_resource_type(info->type_id) );
343
else printf( " %.*s", *((const unsigned char *)res_ptr + info->type_id),
344
(const char *)res_ptr + info->type_id + 1 );
345
if (name->id & 0x8000) printf( " name %04x", (name->id & ~0x8000) );
346
else printf( " name %.*s", *((const unsigned char *)res_ptr + name->id),
347
(const char *)res_ptr + name->id + 1 );
348
printf(" flags %04x length %04x\n", name->flags, name->length << size_shift);
349
350
switch(info->type_id)
351
{
352
case NE_RSCTYPE_STRING:
353
dump_string_data( PRD(name->offset << size_shift, name->length << size_shift),
354
name->length << size_shift, name->id & ~0x8000, " " );
355
break;
356
case NE_RSCTYPE_VERSION:
357
dump_version_data( PRD(name->offset << size_shift, name->length << size_shift),
358
name->length << size_shift, " | " );
359
break;
360
default:
361
dump_data( PRD(name->offset << size_shift, name->length << size_shift),
362
name->length << size_shift, " " );
363
break;
364
}
365
}
366
info = (const NE_TYPEINFO *)name;
367
}
368
}
369
370
static const char *get_export_name( const IMAGE_OS2_HEADER *ne, int ordinal )
371
{
372
static char name[256];
373
const BYTE *pstr;
374
int pass = 0;
375
376
/* search the resident names */
377
378
while (pass < 2)
379
{
380
if (pass == 0) /* resident names */
381
{
382
pstr = (const BYTE *)ne + ne->ne_restab;
383
if (*pstr) pstr += *pstr + 1 + sizeof(WORD); /* skip first entry (module name) */
384
}
385
else /* non-resident names */
386
{
387
if (!ne->ne_cbnrestab) break;
388
pstr = PRD(ne->ne_nrestab, 0);
389
}
390
while (*pstr)
391
{
392
WORD ord = get_word(pstr + *pstr + 1);
393
if (ord == ordinal)
394
{
395
memcpy( name, pstr + 1, *pstr );
396
name[*pstr] = 0;
397
return name;
398
}
399
pstr += *pstr + 1 + sizeof(WORD);
400
}
401
pass++;
402
}
403
name[0] = 0;
404
return name;
405
}
406
407
static void dump_ne_exports( const IMAGE_OS2_HEADER *ne )
408
{
409
const BYTE *ptr = (const BYTE *)ne + ne->ne_enttab;
410
const BYTE *end = ptr + ne->ne_cbenttab;
411
int i, ordinal = 1;
412
413
if (!ne->ne_cbenttab || !*ptr) return;
414
415
printf( "\nExported entry points:\n" );
416
417
while (ptr < end && *ptr)
418
{
419
BYTE count = *ptr++;
420
BYTE type = *ptr++;
421
switch(type)
422
{
423
case 0: /* next bundle */
424
ordinal += count;
425
break;
426
case 0xff: /* movable */
427
for (i = 0; i < count; i++)
428
{
429
printf( " %4d MOVABLE %d:%04x %s\n",
430
ordinal + i, ptr[3], get_word(ptr + 4),
431
get_export_name( ne, ordinal + i ) );
432
ptr += 6;
433
}
434
ordinal += count;
435
break;
436
case 0xfe: /* constant */
437
for (i = 0; i < count; i++)
438
{
439
printf( " %4d CONST %04x %s\n",
440
ordinal + i, get_word(ptr + 1),
441
get_export_name( ne, ordinal + i ) );
442
ptr += 3;
443
}
444
ordinal += count;
445
break;
446
default: /* fixed */
447
for (i = 0; i < count; i++)
448
{
449
printf( " %4d FIXED %d:%04x %s\n",
450
ordinal + i, type, get_word(ptr + 1),
451
get_export_name( ne, ordinal + i ) );
452
ptr += 3;
453
}
454
ordinal += count;
455
break;
456
}
457
}
458
}
459
460
static const char *get_reloc_name( BYTE addr_type, int additive )
461
{
462
switch(addr_type & 0x7f)
463
{
464
case NE_RADDR_LOWBYTE: return additive ? "byte add" : "byte";
465
case NE_RADDR_OFFSET16: return additive ? "off16 add" : "off16";
466
case NE_RADDR_POINTER32: return additive ? "ptr32 add" : "ptr32";
467
case NE_RADDR_SELECTOR: return additive ? "sel add" : "sel";
468
case NE_RADDR_POINTER48: return additive ? "ptr48 add" : "ptr48";
469
case NE_RADDR_OFFSET32: return additive ? "off32 add" : "off32";
470
}
471
return "???";
472
}
473
474
static const char *get_seg_flags( WORD flags )
475
{
476
static char buffer[256];
477
478
buffer[0] = 0;
479
#define ADD_FLAG(x) if (flags & NE_SEGFLAGS_##x) strcat( buffer, " " #x );
480
ADD_FLAG(DATA);
481
ADD_FLAG(ALLOCATED);
482
ADD_FLAG(LOADED);
483
ADD_FLAG(ITERATED);
484
ADD_FLAG(MOVEABLE);
485
ADD_FLAG(SHAREABLE);
486
ADD_FLAG(PRELOAD);
487
ADD_FLAG(EXECUTEONLY);
488
ADD_FLAG(READONLY);
489
ADD_FLAG(RELOC_DATA);
490
ADD_FLAG(SELFLOAD);
491
ADD_FLAG(DISCARDABLE);
492
ADD_FLAG(32BIT);
493
#undef ADD_FLAG
494
if (buffer[0])
495
{
496
buffer[0] = '(';
497
strcat( buffer, ")" );
498
}
499
return buffer;
500
}
501
502
static void dump_relocations( const IMAGE_OS2_HEADER *ne, WORD count,
503
const struct relocation_entry *rep )
504
{
505
const WORD *modref = (const WORD *)((const BYTE *)ne + ne->ne_modtab);
506
const BYTE *mod_name, *func_name;
507
WORD i;
508
509
for (i = 0; i < count; i++, rep++)
510
{
511
int additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
512
switch (rep->relocation_type & 3)
513
{
514
case NE_RELTYPE_ORDINAL:
515
mod_name = (const BYTE *)ne + ne->ne_imptab + modref[rep->target1 - 1];
516
printf( "%6d: %s = %*.*s.%d\n", i + 1, get_reloc_name( rep->address_type, additive ),
517
*mod_name, *mod_name, mod_name + 1, rep->target2 );
518
break;
519
case NE_RELTYPE_NAME:
520
mod_name = (const BYTE *)ne + ne->ne_imptab + modref[rep->target1 - 1];
521
func_name = (const BYTE *)ne + ne->ne_imptab + rep->target2;
522
printf( "%6d: %s = %*.*s.%*.*s\n", i + 1, get_reloc_name( rep->address_type, additive ),
523
*mod_name, *mod_name, mod_name + 1,
524
*func_name, *func_name, func_name + 1 );
525
break;
526
case NE_RELTYPE_INTERNAL:
527
if ((rep->target1 & 0xff) == 0xff)
528
{
529
/* the module itself */
530
mod_name = (const BYTE *)ne + ne->ne_restab;
531
printf( "%6d: %s = %*.*s.%d\n", i + 1, get_reloc_name( rep->address_type, additive ),
532
*mod_name, *mod_name, mod_name + 1, rep->target2 );
533
}
534
else
535
printf( "%6d: %s = %d:%04x\n", i + 1, get_reloc_name( rep->address_type, additive ),
536
rep->target1, rep->target2 );
537
break;
538
case NE_RELTYPE_OSFIXUP:
539
/* Relocation type 7:
540
*
541
* These appear to be used as fixups for the Windows
542
* floating point emulator. Let's just ignore them and
543
* try to use the hardware floating point. Linux should
544
* successfully emulate the coprocessor if it doesn't
545
* exist.
546
*/
547
printf( "%6d: %s = TYPE %d, OFFSET %04x, TARGET %04x %04x\n",
548
i + 1, get_reloc_name( rep->address_type, additive ),
549
rep->relocation_type, rep->offset,
550
rep->target1, rep->target2 );
551
break;
552
}
553
}
554
}
555
556
static void dump_ne_segment( const IMAGE_OS2_HEADER *ne, int segnum )
557
{
558
const struct ne_segtable_entry *table = (const struct ne_segtable_entry *)((const BYTE *)ne + ne->ne_segtab);
559
const struct ne_segtable_entry *seg = table + segnum - 1;
560
561
printf( "\nSegment %d:\n", segnum );
562
printf( " File offset: %08x\n", seg->seg_data_offset << ne->ne_align );
563
printf( " Length: %08x\n", seg->seg_data_length );
564
printf( " Flags: %08x %s\n", seg->seg_flags, get_seg_flags(seg->seg_flags) );
565
printf( " Alloc size: %08x\n", seg->min_alloc );
566
if (seg->seg_flags & NE_SEGFLAGS_RELOC_DATA)
567
{
568
const BYTE *ptr = PRD((seg->seg_data_offset << ne->ne_align) + seg->seg_data_length, 0);
569
WORD count = get_word(ptr);
570
ptr += sizeof(WORD);
571
printf( " Relocations:\n" );
572
dump_relocations( ne, count, (const struct relocation_entry *)ptr );
573
}
574
}
575
576
void ne_dump( void )
577
{
578
unsigned int i;
579
const IMAGE_DOS_HEADER *dos;
580
const IMAGE_OS2_HEADER *ne;
581
582
dos = PRD(0, sizeof(*dos));
583
if (!dos) return;
584
ne = PRD(dos->e_lfanew, sizeof(*ne));
585
print_fake_dll();
586
587
if (globals.do_dumpheader || !globals.dumpsect)
588
dump_ne_header( ne );
589
if (globals.do_dumpheader)
590
dump_ne_names( ne );
591
592
if (globals_dump_sect("resource"))
593
dump_ne_resources( ne );
594
if (globals_dump_sect("export"))
595
dump_ne_exports( ne );
596
if (globals.do_dumpheader)
597
for (i = 1; i <= ne->ne_cseg; i++) dump_ne_segment( ne, i );
598
}
599
600