1 /* nlmconv.c -- NLM conversion program
2 Copyright (C) 1993 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program 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
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Written by Ian Lance Taylor <ian@cygnus.com>.
22 This program can be used to convert any appropriate object file
23 into a NetWare Loadable Module (an NLM). It will accept a linker
24 specification file which is identical to that accepted by the
25 NetWare linker, NLMLINK, except that the INPUT command, normally
26 used to give a list of object files to link together, is not used.
27 This program will convert only a single object file. */
31 #include <sys/types.h>
38 /* Internal BFD NLM header. */
42 /* If strerror is just a macro, we want to use the one from libiberty
43 since it will handle undefined values. */
45 extern char *strerror ();
47 /* Global variables. */
49 /* The name used to invoke the program. */
52 /* The version number. */
53 extern char *program_version
;
55 /* The symbols table. */
56 static asymbol
**symbols
;
58 /* Local variables. */
60 /* The list of long options. */
61 static struct option long_options
[] =
63 { "header-info", required_argument
, 0, 'T' },
64 { "help", no_argument
, 0, 'H' },
65 { "input-format", required_argument
, 0, 'I' },
66 { "output-format", required_argument
, 0, 'O' },
67 { "version", no_argument
, 0, 'v' },
68 { NULL
, no_argument
, 0, 0 }
73 static void show_help
PARAMS ((void));
74 static void show_usage
PARAMS ((FILE *, int));
75 static const char *select_output_format
PARAMS ((enum bfd_architecture
,
77 static void setup_sections
PARAMS ((bfd
*, asection
*, PTR
));
78 static void copy_sections
PARAMS ((bfd
*, asection
*, PTR
));
79 static void mangle_relocs
PARAMS ((bfd
*, arelent
**,
80 bfd_size_type
, char *,
82 static void i386_mangle_relocs
PARAMS ((bfd
*, arelent
**, bfd_size_type
,
83 char *, bfd_size_type
));
85 /* The main routine. */
93 const char *input_format
= NULL
;
94 const char *output_format
= NULL
;
95 const char *header_file
= NULL
;
98 unsigned int symcount
;
100 char inlead
, outlead
;
101 boolean gotstart
, gotexit
, gotcheck
;
103 FILE *custom_data
, *help_data
, *message_data
, *rpc_data
;
104 bfd_size_type custom_size
, help_size
, message_size
, module_size
, rpc_size
;
105 asection
*custom_section
, *help_section
, *message_section
, *module_section
;
106 asection
*rpc_section
;
109 program_name
= argv
[0];
113 while ((opt
= getopt_long (argc
, argv
, "HI:O:T:v", long_options
, (int *) 0))
122 input_format
= optarg
;
125 output_format
= optarg
;
128 header_file
= optarg
;
131 printf ("GNU %s version %s\n", program_name
, program_version
);
137 show_usage (stderr
, 1);
142 if (optind
+ 2 != argc
)
143 show_usage (stderr
, 1);
145 if (strcmp (argv
[optind
], argv
[optind
+ 1]) == 0)
147 fprintf (stderr
, "%s: input and output files must be different\n",
152 inbfd
= bfd_openr (argv
[optind
], input_format
);
154 bfd_fatal (argv
[optind
]);
156 if (! bfd_check_format (inbfd
, bfd_object
))
157 bfd_fatal (argv
[optind
]);
159 if (output_format
== NULL
)
160 output_format
= select_output_format (bfd_get_arch (inbfd
),
161 bfd_get_mach (inbfd
),
162 inbfd
->xvec
->byteorder_big_p
);
164 assert (output_format
!= NULL
);
165 outbfd
= bfd_openw (argv
[optind
+ 1], output_format
);
167 bfd_fatal (argv
[optind
+ 1]);
168 if (! bfd_set_format (outbfd
, bfd_object
))
169 bfd_fatal (argv
[optind
+ 1]);
171 assert (outbfd
->xvec
->flavour
== bfd_target_nlm_flavour
);
173 if (bfd_arch_get_compatible (inbfd
, outbfd
) == NULL
)
175 "%s: warning:input and output formats are not compatible\n",
178 /* Initialize the header information to default values. */
179 fixed_hdr
= nlm_fixed_header (outbfd
);
180 var_hdr
= nlm_variable_header (outbfd
);
181 version_hdr
= nlm_version_header (outbfd
);
182 copyright_hdr
= nlm_copyright_header (outbfd
);
183 extended_hdr
= nlm_extended_header (outbfd
);
184 check_procedure
= NULL
;
187 exit_procedure
= "_Stop";
188 export_symbols
= NULL
;
192 import_symbols
= NULL
;
195 sharelib_file
= NULL
;
196 start_procedure
= "_Prelude";
202 /* Parse the header file (if there is one). */
203 if (header_file
!= NULL
)
205 if (! nlmlex_file (header_file
)
207 || parse_errors
!= 0)
211 /* Start copying the input BFD to the output BFD. */
212 if (! bfd_set_file_flags (outbfd
, bfd_get_file_flags (inbfd
)))
213 bfd_fatal (bfd_get_filename (outbfd
));
215 symbols
= (asymbol
**) xmalloc (get_symtab_upper_bound (inbfd
));
216 symcount
= bfd_canonicalize_symtab (inbfd
, symbols
);
218 /* Adjust symbol information. */
219 inlead
= bfd_get_symbol_leading_char (inbfd
);
220 outlead
= bfd_get_symbol_leading_char (outbfd
);
224 for (i
= 0; i
< symcount
; i
++)
226 register asymbol
*sym
;
230 /* Add or remove a leading underscore. */
231 if (inlead
!= outlead
)
235 if (bfd_asymbol_name (sym
)[0] == inlead
)
243 new = xmalloc (strlen (bfd_asymbol_name (sym
)) + 1);
245 strcpy (new + 1, bfd_asymbol_name (sym
) + 1);
254 new = xmalloc (strlen (bfd_asymbol_name (sym
)) + 2);
256 strcpy (new + 1, bfd_asymbol_name (sym
));
261 /* If this is a global symbol, see if it's in the export list.
262 Change the prefix if necessary. */
263 if ((sym
->flags
& (BSF_EXPORT
| BSF_GLOBAL
)) != 0
264 && export_symbols
!= NULL
)
266 register struct string_list
*l
;
268 for (l
= export_symbols
; l
!= NULL
; l
= l
->next
)
270 if (strcmp (l
->string
, bfd_asymbol_name (sym
)) == 0)
276 zbase
= strchr (l
->string
, '@');
278 && strcmp (zbase
+ 1, bfd_asymbol_name (sym
)) == 0)
280 sym
->name
= l
->string
;
287 "%s: warning: symbol %s exported but not in export list\n",
288 program_name
, bfd_asymbol_name (sym
));
291 /* If it's an undefined symbol, see if it's on the import list.
292 Change the prefix if necessary. */
293 if (bfd_get_section (sym
) == &bfd_und_section
294 && import_symbols
!= NULL
)
296 register struct string_list
*l
;
298 for (l
= import_symbols
; l
!= NULL
; l
= l
->next
)
300 if (strcmp (l
->string
, bfd_asymbol_name (sym
)) == 0)
306 zbase
= strchr (l
->string
, '@');
308 && strcmp (zbase
+ 1, bfd_asymbol_name (sym
)) == 0)
310 sym
->name
= l
->string
;
317 "%s: warning: symbol %s imported but not in import list\n",
318 program_name
, bfd_asymbol_name (sym
));
321 /* See if it's one of the special named symbols. */
322 if (strcmp (bfd_asymbol_name (sym
), start_procedure
) == 0)
324 if (! bfd_set_start_address (outbfd
, bfd_asymbol_value (sym
)))
325 bfd_fatal ("set start address");
328 if (strcmp (bfd_asymbol_name (sym
), exit_procedure
) == 0)
330 nlm_fixed_header (outbfd
)->exitProcedureOffset
=
331 bfd_asymbol_value (sym
);
334 if (check_procedure
!= NULL
335 && strcmp (bfd_asymbol_name (sym
), check_procedure
) == 0)
337 nlm_fixed_header (outbfd
)->checkUnloadProcedureOffset
=
338 bfd_asymbol_value (sym
);
343 bfd_set_symtab (outbfd
, symbols
, symcount
);
346 fprintf (stderr
, "%s: warning: START procedure %s not defined\n",
347 program_name
, start_procedure
);
349 fprintf (stderr
, "%s: warning: EXIT procedure %s not defined\n",
350 program_name
, exit_procedure
);
351 if (check_procedure
!= NULL
353 fprintf (stderr
, "%s: warning: CHECK procedure %s not defined\n",
354 program_name
, check_procedure
);
356 /* Set up the sections. */
357 bfd_map_over_sections (inbfd
, setup_sections
, (PTR
) outbfd
);
359 /* Add additional sections required for the header information. */
360 if (custom_file
!= NULL
)
362 custom_data
= fopen (custom_file
, "r");
363 if (custom_data
== NULL
364 || fstat (fileno (custom_data
), &st
) < 0)
366 fprintf (stderr
, "%s:%s: %s\n", program_name
, custom_file
,
372 custom_size
= st
.st_size
;
373 custom_section
= bfd_make_section (outbfd
, ".nlmcustom");
374 if (custom_section
== NULL
375 || ! bfd_set_section_size (outbfd
, custom_section
, custom_size
)
376 || ! bfd_set_section_flags (outbfd
, custom_section
,
378 bfd_fatal ("custom section");
381 if (help_file
!= NULL
)
383 help_data
= fopen (help_file
, "r");
384 if (help_data
== NULL
385 || fstat (fileno (help_data
), &st
) < 0)
387 fprintf (stderr
, "%s:%s: %s\n", program_name
, help_file
,
393 help_size
= st
.st_size
;
394 help_section
= bfd_make_section (outbfd
, ".nlmhelp");
395 if (help_section
== NULL
396 || ! bfd_set_section_size (outbfd
, help_section
, help_size
)
397 || ! bfd_set_section_flags (outbfd
, help_section
,
399 bfd_fatal ("help section");
400 strncpy (nlm_extended_header (outbfd
)->stamp
, "MeSsAgEs", 8);
403 if (message_file
!= NULL
)
405 message_data
= fopen (message_file
, "r");
406 if (message_data
== NULL
407 || fstat (fileno (message_data
), &st
) < 0)
409 fprintf (stderr
, "%s:%s: %s\n", program_name
, message_file
,
415 message_size
= st
.st_size
;
416 message_section
= bfd_make_section (outbfd
, ".nlmmessages");
417 if (message_section
== NULL
418 || ! bfd_set_section_size (outbfd
, message_section
, message_size
)
419 || ! bfd_set_section_flags (outbfd
, message_section
,
421 bfd_fatal ("message section");
422 strncpy (nlm_extended_header (outbfd
)->stamp
, "MeSsAgEs", 8);
427 struct string_list
*l
;
430 for (l
= modules
; l
!= NULL
; l
= l
->next
)
431 module_size
+= strlen (l
->string
) + 1;
432 module_section
= bfd_make_section (outbfd
, ".nlmmodules");
433 if (module_section
== NULL
434 || ! bfd_set_section_size (outbfd
, module_section
, module_size
)
435 || ! bfd_set_section_flags (outbfd
, module_section
,
437 bfd_fatal ("module section");
439 if (rpc_file
!= NULL
)
441 rpc_data
= fopen (rpc_file
, "r");
443 || fstat (fileno (rpc_data
), &st
) < 0)
445 fprintf (stderr
, "%s:%s: %s\n", program_name
, rpc_file
,
451 rpc_size
= st
.st_size
;
452 rpc_section
= bfd_make_section (outbfd
, ".nlmrpc");
453 if (rpc_section
== NULL
454 || ! bfd_set_section_size (outbfd
, rpc_section
, rpc_size
)
455 || ! bfd_set_section_flags (outbfd
, rpc_section
,
457 bfd_fatal ("rpc section");
458 strncpy (nlm_extended_header (outbfd
)->stamp
, "MeSsAgEs", 8);
462 /* Copy over the sections. */
463 bfd_map_over_sections (inbfd
, copy_sections
, (PTR
) outbfd
);
465 /* Finish up the header information. */
466 if (custom_file
!= NULL
)
470 data
= xmalloc (custom_size
);
471 if (fread (data
, 1, custom_size
, custom_data
) != custom_size
)
472 fprintf (stderr
, "%s:%s: read: %s\n", program_name
, custom_file
,
476 if (! bfd_set_section_contents (outbfd
, custom_section
, data
,
477 (file_ptr
) 0, custom_size
))
478 bfd_fatal ("custom section");
479 nlm_fixed_header (outbfd
)->customDataOffset
=
480 custom_section
->filepos
;
481 nlm_fixed_header (outbfd
)->customDataSize
= custom_size
;
487 /* As a special hack, the backend recognizes a debugInfoOffset
488 of -1 to mean that it should not output any debugging
489 information. This can not be handling by fiddling with the
490 symbol table because exported symbols appear in both the
491 export information and the debugging information. */
492 nlm_fixed_header (outbfd
)->debugInfoOffset
= (file_ptr
) -1;
494 if (map_file
!= NULL
)
496 "%s: MAP and FULLMAP are not supported; try ld -M\n",
498 if (help_file
!= NULL
)
502 data
= xmalloc (help_size
);
503 if (fread (data
, 1, help_size
, help_data
) != help_size
)
504 fprintf (stderr
, "%s:%s: read: %s\n", program_name
, help_file
,
508 if (! bfd_set_section_contents (outbfd
, help_section
, data
,
509 (file_ptr
) 0, help_size
))
510 bfd_fatal ("help section");
511 nlm_extended_header (outbfd
)->helpFileOffset
=
512 help_section
->filepos
;
513 nlm_extended_header (outbfd
)->helpFileLength
= help_size
;
517 if (message_file
!= NULL
)
521 data
= xmalloc (message_size
);
522 if (fread (data
, 1, message_size
, message_data
) != message_size
)
523 fprintf (stderr
, "%s:%s: read: %s\n", program_name
, message_file
,
527 if (! bfd_set_section_contents (outbfd
, message_section
, data
,
528 (file_ptr
) 0, message_size
))
529 bfd_fatal ("message section");
530 nlm_extended_header (outbfd
)->messageFileOffset
=
531 message_section
->filepos
;
532 nlm_extended_header (outbfd
)->messageFileLength
= message_size
;
534 /* FIXME: Are these offsets correct on all platforms? Are
535 they 32 bits on all platforms? What endianness? */
536 nlm_extended_header (outbfd
)->languageID
=
537 bfd_h_get_32 (outbfd
, (bfd_byte
*) data
+ 106);
538 nlm_extended_header (outbfd
)->messageCount
=
539 bfd_h_get_32 (outbfd
, (bfd_byte
*) data
+ 110);
547 struct string_list
*l
;
550 data
= xmalloc (module_size
);
553 for (l
= modules
; l
!= NULL
; l
= l
->next
)
555 *set
= strlen (l
->string
);
556 strncpy (set
+ 1, l
->string
, *set
);
560 if (! bfd_set_section_contents (outbfd
, module_section
, data
,
561 (file_ptr
) 0, module_size
))
562 bfd_fatal ("module section");
563 nlm_fixed_header (outbfd
)->moduleDependencyOffset
=
564 module_section
->filepos
;
565 nlm_fixed_header (outbfd
)->numberOfModuleDependencies
= c
;
567 if (rpc_file
!= NULL
)
571 data
= xmalloc (rpc_size
);
572 if (fread (data
, 1, rpc_size
, rpc_data
) != rpc_size
)
573 fprintf (stderr
, "%s:%s: read: %s\n", program_name
, rpc_file
,
577 if (! bfd_set_section_contents (outbfd
, rpc_section
, data
,
578 (file_ptr
) 0, rpc_size
))
579 bfd_fatal ("rpc section");
580 nlm_extended_header (outbfd
)->RPCDataOffset
=
581 rpc_section
->filepos
;
582 nlm_extended_header (outbfd
)->RPCDataLength
= rpc_size
;
586 len
= strlen (argv
[optind
+ 1]);
587 if (len
> NLM_MODULE_NAME_SIZE
- 2)
588 len
= NLM_MODULE_NAME_SIZE
- 2;
589 nlm_fixed_header (outbfd
)->moduleName
[0] = len
;
590 strncpy (nlm_fixed_header (outbfd
)->moduleName
+ 1, argv
[optind
+ 1],
591 NLM_MODULE_NAME_SIZE
- 2);
592 nlm_fixed_header (outbfd
)->moduleName
[NLM_MODULE_NAME_SIZE
- 1] = '\0';
593 strncpy (nlm_variable_header (outbfd
)->oldThreadName
, " LONG",
594 NLM_OLD_THREAD_NAME_LENGTH
);
596 if (! bfd_close (outbfd
))
597 bfd_fatal (argv
[optind
+ 1]);
598 if (! bfd_close (inbfd
))
599 bfd_fatal (argv
[optind
]);
604 /* Display a help message and exit. */
609 printf ("%s: Convert an object file into a NetWare Loadable Module\n",
611 show_usage (stdout
, 0);
614 /* Show a usage message and exit. */
617 show_usage (file
, status
)
622 Usage: %s [-Hv] [-I format] [-O format] [-T header-file]\n\
623 [--input-format=format] [--output-format=format]\n\
624 [--header-file=file] [--help] [--version]\n\
630 /* Select the output format based on the input architecture, machine,
631 and endianness. This chooses the appropriate NLM target. */
634 select_output_format (arch
, mach
, bigendian
)
635 enum bfd_architecture arch
;
644 fprintf (stderr
, "%s: no default NLM format for %s\n",
645 program_name
, bfd_printable_arch_mach (arch
, mach
));
653 /* The BFD sections are copied in two passes. This function sets up
654 the section name, size, etc. */
657 setup_sections (inbfd
, insec
, data_ptr
)
662 bfd
*outbfd
= (bfd
*) data_ptr
;
665 outsec
= bfd_get_section_by_name (outbfd
, bfd_section_name (inbfd
, insec
));
668 outsec
= bfd_make_section (outbfd
, bfd_section_name (inbfd
, insec
));
670 bfd_fatal ("make section");
673 insec
->output_section
= outsec
;
674 insec
->output_offset
= 0;
676 if (! bfd_set_section_size (outbfd
, outsec
,
677 bfd_section_size (inbfd
, insec
)))
678 bfd_fatal ("set section size");
680 if (! bfd_set_section_vma (outbfd
, outsec
,
681 bfd_section_vma (inbfd
, insec
)))
682 bfd_fatal ("set section vma");
684 if (! bfd_set_section_alignment (outbfd
, outsec
,
685 bfd_section_alignment (inbfd
, insec
)))
686 bfd_fatal ("set section alignment");
688 if (! bfd_set_section_flags (outbfd
, outsec
,
689 bfd_get_section_flags (inbfd
, insec
)))
690 bfd_fatal ("set section flags");
693 /* Copy the section contents. */
696 copy_sections (inbfd
, insec
, data_ptr
)
701 bfd
*outbfd
= (bfd
*) data_ptr
;
705 bfd_size_type reloc_size
;
707 outsec
= bfd_get_section_by_name (outbfd
, bfd_section_name (inbfd
, insec
));
708 assert (outsec
!= NULL
);
710 size
= bfd_get_section_size_before_reloc (insec
);
714 /* FIXME: Why are these necessary? */
715 insec
->_cooked_size
= insec
->_raw_size
;
716 insec
->reloc_done
= true;
718 if ((bfd_get_section_flags (inbfd
, insec
) & SEC_HAS_CONTENTS
) == 0)
722 contents
= xmalloc (size
);
723 if (! bfd_get_section_contents (inbfd
, insec
, contents
,
725 bfd_fatal (bfd_get_filename (inbfd
));
728 reloc_size
= bfd_get_reloc_upper_bound (inbfd
, insec
);
730 bfd_set_reloc (outbfd
, outsec
, (arelent
**) NULL
, 0);
734 bfd_size_type reloc_count
;
736 relocs
= (arelent
**) xmalloc (reloc_size
);
737 reloc_count
= bfd_canonicalize_reloc (inbfd
, insec
, relocs
, symbols
);
738 mangle_relocs (outbfd
, relocs
, reloc_count
, (char *) contents
, size
);
739 bfd_set_reloc (outbfd
, outsec
, relocs
, reloc_count
);
742 if (contents
!= NULL
)
744 if (! bfd_set_section_contents (outbfd
, outsec
, contents
,
746 bfd_fatal (bfd_get_filename (outbfd
));
751 /* Some, perhaps all, NetWare targets require changing the relocs used
752 by the input formats. */
755 mangle_relocs (outbfd
, relocs
, reloc_count
, contents
, contents_size
)
758 bfd_size_type reloc_count
;
760 bfd_size_type contents_size
;
762 switch (bfd_get_arch (outbfd
))
765 i386_mangle_relocs (outbfd
, relocs
, reloc_count
, contents
,
773 /* NetWare on the i386 supports a restricted set of relocs, which are
774 different from those used on other i386 targets. This routine
775 converts the relocs. It is, obviously, very target dependent. At
776 the moment, the nlm32-i386 backend performs similar translations;
777 however, it is more reliable and efficient to do them here. */
779 static reloc_howto_type nlm_i386_pcrel_howto
=
782 2, /* size (0 = byte, 1 = short, 2 = long) */
784 true, /* pc_relative */
786 complain_overflow_signed
, /* complain_on_overflow */
787 0, /* special_function */
789 true, /* partial_inplace */
790 0xffffffff, /* src_mask */
791 0xffffffff, /* dst_mask */
792 true); /* pcrel_offset */
795 i386_mangle_relocs (outbfd
, relocs
, reloc_count
, contents
, contents_size
)
798 bfd_size_type reloc_count
;
800 bfd_size_type contents_size
;
802 while (reloc_count
-- != 0)
809 sym
= *rel
->sym_ptr_ptr
;
811 /* Note that no serious harm will ensue if we fail to change a
812 reloc. The backend will fail when writing out the reloc. */
814 /* Make sure this reloc is within the data we have. We use only
815 4 byte relocs here, so we insist on having 4 bytes. */
816 if (rel
->address
+ 4 > contents_size
)
819 /* NetWare doesn't support reloc addends, so we get rid of them
820 here by simply adding them into the object data. We handle
821 the symbol value, if any, the same way. */
822 addend
= rel
->addend
;
823 if (! bfd_is_com_section (bfd_get_section (sym
)))
824 addend
+= sym
->value
;
827 && rel
->howto
!= NULL
828 && rel
->howto
->rightshift
== 0
829 && rel
->howto
->size
== 2
830 && rel
->howto
->bitsize
== 32
831 && rel
->howto
->bitpos
== 0
832 && rel
->howto
->src_mask
== 0xffffffff
833 && rel
->howto
->dst_mask
== 0xffffffff)
837 val
= bfd_get_32 (outbfd
, contents
+ rel
->address
);
839 bfd_put_32 (outbfd
, val
, contents
+ rel
->address
);
841 /* Adjust the reloc for the changes we just made. */
843 if (! bfd_is_com_section (bfd_get_section (sym
))
845 rel
->sym_ptr_ptr
= bfd_get_section (sym
)->symbol_ptr_ptr
;
848 /* NetWare uses a reloc with pcrel_offset set. We adjust
849 pc_relative relocs accordingly. We are going to change the
850 howto field, so we can only do this if the current one is
851 compatible. We should check that special_function is NULL
852 here, but at the moment coff-i386 uses a special_function
853 which does not affect what we are doing here. */
854 if (rel
->howto
!= NULL
855 && rel
->howto
->pc_relative
856 && ! rel
->howto
->pcrel_offset
857 && rel
->howto
->rightshift
== 0
858 && rel
->howto
->size
== 2
859 && rel
->howto
->bitsize
== 32
860 && rel
->howto
->bitpos
== 0
861 && rel
->howto
->src_mask
== 0xffffffff
862 && rel
->howto
->dst_mask
== 0xffffffff)
866 /* When pcrel_offset is not set, it means that the negative
867 of the address of the memory location is stored in the
868 memory location. We must add it back in. */
869 val
= bfd_get_32 (outbfd
, contents
+ rel
->address
);
871 bfd_put_32 (outbfd
, val
, contents
+ rel
->address
);
873 /* We must change to a new howto. */
874 rel
->howto
= &nlm_i386_pcrel_howto
;