1 /*-
2  * Copyright (c) 2012,2013 Kai Wang
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include "ld.h"
28 #include "ld_arch.h"
29 #include "ld_dynamic.h"
30 #include "ld_input.h"
31 #include "ld_output.h"
32 #include "ld_reloc.h"
33 #include "ld_symbols.h"
34 #include "ld_utils.h"
35 #include "i386.h"
36 
37 ELFTC_VCSID("$Id: i386.c 3402 2016-02-13 15:35:06Z jkoshy $");
38 
39 static void _create_plt_reloc(struct ld *ld, struct ld_symbol *lsb,
40     uint64_t offset);
41 static void _create_got_reloc(struct ld *ld, struct ld_symbol *lsb,
42     uint64_t type, uint64_t offset);
43 static void _create_copy_reloc(struct ld *ld, struct ld_symbol *lsb);
44 static void _create_dynamic_reloc(struct ld *ld, struct ld_input_section *is,
45     struct ld_symbol *lsb, uint64_t type, uint64_t offset);
46 static void _scan_reloc(struct ld *ld, struct ld_input_section *is,
47     struct ld_reloc_entry *lre);
48 static struct ld_input_section *_find_and_create_got_section(struct ld *ld,
49     int create);
50 static struct ld_input_section *_find_and_create_gotplt_section(struct ld *ld,
51     int create);
52 static struct ld_input_section *_find_and_create_plt_section(struct ld *ld,
53     int create);
54 static uint64_t _get_max_page_size(struct ld *ld);
55 static uint64_t _get_common_page_size(struct ld *ld);
56 static void _process_reloc(struct ld *ld, struct ld_input_section *is,
57     struct ld_reloc_entry *lre, struct ld_symbol *lsb, uint8_t *buf);
58 static const char *_reloc2str(uint64_t r);
59 static void _reserve_got_entry(struct ld *ld, struct ld_symbol *lsb, int num);
60 static void _reserve_gotplt_entry(struct ld *ld, struct ld_symbol *lsb);
61 static void _reserve_plt_entry(struct ld *ld, struct ld_symbol *lsb);
62 static int _is_absolute_reloc(uint64_t r);
63 static int _is_relative_reloc(uint64_t r);
64 static void _warn_pic(struct ld *ld, struct ld_reloc_entry *lre);
65 static uint32_t _got_offset(struct ld *ld, struct ld_symbol *lsb);
66 
67 static uint64_t
_get_max_page_size(struct ld * ld)68 _get_max_page_size(struct ld *ld)
69 {
70 
71 	(void) ld;
72 	return (0x1000);
73 }
74 
75 static uint64_t
_get_common_page_size(struct ld * ld)76 _get_common_page_size(struct ld *ld)
77 {
78 
79 	(void) ld;
80 	return (0x1000);
81 }
82 
83 static const char *
_reloc2str(uint64_t r)84 _reloc2str(uint64_t r)
85 {
86 	static char s[32];
87 
88 	switch (r) {
89 		case 0: return "R_386_NONE";
90 		case 1: return "R_386_32";
91 		case 2: return "R_386_PC32";
92 		case 3: return "R_386_GOT32";
93 		case 4: return "R_386_PLT32";
94 		case 5: return "R_386_COPY";
95 		case 6: return "R_386_GLOB_DAT";
96 		case 7: return "R_386_JUMP_SLOT";
97 		case 8: return "R_386_RELATIVE";
98 		case 9: return "R_386_GOTOFF";
99 		case 10: return "R_386_GOTPC";
100 		case 14: return "R_386_TLS_TPOFF";
101 		case 15: return "R_386_TLS_IE";
102 		case 16: return "R_386_TLS_GOTI";
103 		case 17: return "R_386_TLS_LE";
104 		case 18: return "R_386_TLS_GD";
105 		case 19: return "R_386_TLS_LDM";
106 		case 24: return "R_386_TLS_GD_32";
107 		case 25: return "R_386_TLS_GD_PUSH";
108 		case 26: return "R_386_TLS_GD_CALL";
109 		case 27: return "R_386_TLS_GD_POP";
110 		case 28: return "R_386_TLS_LDM_32";
111 		case 29: return "R_386_TLS_LDM_PUSH";
112 		case 30: return "R_386_TLS_LDM_CALL";
113 		case 31: return "R_386_TLS_LDM_POP";
114 		case 32: return "R_386_TLS_LDO_32";
115 		case 33: return "R_386_TLS_IE_32";
116 		case 34: return "R_386_TLS_LE_32";
117 		case 35: return "R_386_TLS_DTPMOD32";
118 		case 36: return "R_386_TLS_DTPOFF32";
119 		case 37: return "R_386_TLS_TPOFF32";
120 
121 	default:
122 		snprintf(s, sizeof(s), "<unkown: %ju>", (uintmax_t) r);
123 		return (s);
124 	}
125 }
126 
127 static int
_is_absolute_reloc(uint64_t r)128 _is_absolute_reloc(uint64_t r)
129 {
130 
131 	if (r == R_386_32)
132 		return (1);
133 
134 	return (0);
135 }
136 
137 static int
_is_relative_reloc(uint64_t r)138 _is_relative_reloc(uint64_t r)
139 {
140 
141 	if (r == R_386_RELATIVE)
142 		return (1);
143 
144 	return (0);
145 }
146 
147 static void
_warn_pic(struct ld * ld,struct ld_reloc_entry * lre)148 _warn_pic(struct ld *ld, struct ld_reloc_entry *lre)
149 {
150 	struct ld_symbol *lsb;
151 
152 	lsb = lre->lre_sym;
153 
154 	if (lsb->lsb_bind != STB_LOCAL)
155 		ld_warn(ld, "relocation %s against `%s' can not be used"
156 		    " by runtime linker; recompile with -fPIC",
157 		    _reloc2str(lre->lre_type), lsb->lsb_name);
158 	else
159 		ld_warn(ld, "relocation %s can not be used by runtime linker;"
160 		    " recompile with -fPIC", _reloc2str(lre->lre_type));
161 }
162 
163 static struct ld_input_section *
_find_and_create_got_section(struct ld * ld,int create)164 _find_and_create_got_section(struct ld *ld, int create)
165 {
166 	struct ld_input_section *is;
167 
168 	/* Check if the GOT section is already created. */
169 	is = ld_input_find_internal_section(ld, ".got");
170 	if (is != NULL)
171 		return (is);
172 
173 	if (create) {
174 		is = ld_input_add_internal_section(ld, ".got");
175 		is->is_entsize = 4;
176 		is->is_align = 4;
177 		is->is_type = SHT_PROGBITS;
178 		is->is_flags = SHF_ALLOC | SHF_WRITE;
179 	}
180 
181 	return (is);
182 }
183 
184 static struct ld_input_section *
_find_and_create_gotplt_section(struct ld * ld,int create)185 _find_and_create_gotplt_section(struct ld *ld, int create)
186 {
187 	struct ld_input_section *is;
188 
189 	/* Check if the GOT (for PLT) section is already created. */
190 	is = ld_input_find_internal_section(ld, ".got.plt");
191 	if (is != NULL)
192 		return (is);
193 
194 	if (create) {
195 		is = ld_input_add_internal_section(ld, ".got.plt");
196 		is->is_entsize = 4;
197 		is->is_align = 4;
198 		is->is_type = SHT_PROGBITS;
199 		is->is_flags = SHF_ALLOC | SHF_WRITE;
200 
201 		/* Reserve space for the initial entries. */
202 		(void) ld_input_reserve_ibuf(is, 3);
203 
204 		/* Create _GLOBAL_OFFSET_TABLE_ symbol. */
205 		ld_symbols_add_internal(ld, "_GLOBAL_OFFSET_TABLE_", 0, 0,
206 		    is->is_index, STB_LOCAL, STT_OBJECT, STV_HIDDEN, is, NULL);
207 	}
208 
209 	return (is);
210 }
211 
212 static struct ld_input_section *
_find_and_create_plt_section(struct ld * ld,int create)213 _find_and_create_plt_section(struct ld *ld, int create)
214 {
215 	struct ld_input_section *is;
216 
217 	/* Check if the PLT section is already created. */
218 	is = ld_input_find_internal_section(ld, ".plt");
219 	if (is != NULL)
220 		return (is);
221 
222 	if (create) {
223 		is = ld_input_add_internal_section(ld, ".plt");
224 		is->is_entsize = 4;
225 		is->is_align = 4;
226 		is->is_type = SHT_PROGBITS;
227 		is->is_flags = SHF_ALLOC | SHF_EXECINSTR;
228 
229 		/* Reserve space for the initial entry. */
230 		(void) ld_input_reserve_ibuf(is, 1);
231 	}
232 
233 	return (is);
234 }
235 
236 static void
_reserve_got_entry(struct ld * ld,struct ld_symbol * lsb,int num)237 _reserve_got_entry(struct ld *ld, struct ld_symbol *lsb, int num)
238 {
239 	struct ld_input_section *is;
240 
241 	is = _find_and_create_got_section(ld, 1);
242 
243 	/* Check if the entry already has a GOT entry. */
244 	if (lsb->lsb_got)
245 		return;
246 
247 	/* Reserve GOT entries. */
248 	lsb->lsb_got_off = ld_input_reserve_ibuf(is, num);
249 	lsb->lsb_got = 1;
250 }
251 
252 static void
_reserve_gotplt_entry(struct ld * ld,struct ld_symbol * lsb)253 _reserve_gotplt_entry(struct ld *ld, struct ld_symbol *lsb)
254 {
255 	struct ld_input_section *is;
256 
257 	is = _find_and_create_gotplt_section(ld, 1);
258 
259 	/* Reserve a GOT entry for PLT. */
260 	(void) ld_input_reserve_ibuf(is, 1);
261 
262 	/*
263 	 * Record a R_386_JUMP_SLOT entry for this symbol. Note that
264 	 * we don't need to record the offset (relative to the GOT section)
265 	 * here, since the PLT relocations will be sorted later and we
266 	 * will generate GOT section according to the new order.
267 	 */
268 	_create_plt_reloc(ld, lsb, 0);
269 }
270 
271 static void
_reserve_plt_entry(struct ld * ld,struct ld_symbol * lsb)272 _reserve_plt_entry(struct ld *ld, struct ld_symbol *lsb)
273 {
274 	struct ld_input_section *is;
275 
276 	is = _find_and_create_plt_section(ld, 1);
277 
278 	(void) ld_input_reserve_ibuf(is, 1);
279 	lsb->lsb_plt = 1;
280 }
281 
282 static void
_create_plt_reloc(struct ld * ld,struct ld_symbol * lsb,uint64_t offset)283 _create_plt_reloc(struct ld *ld, struct ld_symbol *lsb, uint64_t offset)
284 {
285 
286 	ld_reloc_create_entry(ld, ".rel.plt", NULL, R_386_JUMP_SLOT,
287 	    lsb, offset, 0);
288 
289 	lsb->lsb_dynrel = 1;
290 }
291 
292 static void
_create_got_reloc(struct ld * ld,struct ld_symbol * lsb,uint64_t type,uint64_t offset)293 _create_got_reloc(struct ld *ld, struct ld_symbol *lsb, uint64_t type,
294     uint64_t offset)
295 {
296 	struct ld_input_section *tis;
297 
298 	tis = _find_and_create_got_section(ld, 0);
299 	assert(tis != NULL);
300 
301 	ld_reloc_create_entry(ld, ".rel.got", tis, type, lsb, offset, 0);
302 
303 	if (type != R_386_RELATIVE)
304 		lsb->lsb_dynrel = 1;
305 }
306 
307 static void
_create_copy_reloc(struct ld * ld,struct ld_symbol * lsb)308 _create_copy_reloc(struct ld *ld, struct ld_symbol *lsb)
309 {
310 	struct ld_input_section *tis;
311 
312 	ld_dynamic_reserve_dynbss_entry(ld, lsb);
313 
314 	tis = ld_input_find_internal_section(ld, ".dynbss");
315 	assert(tis != NULL);
316 
317 	ld_reloc_create_entry(ld, ".rel.bss", tis, R_386_COPY, lsb,
318 	    lsb->lsb_value, 0);
319 
320 	lsb->lsb_dynrel = 1;
321 }
322 
323 static void
_create_dynamic_reloc(struct ld * ld,struct ld_input_section * is,struct ld_symbol * lsb,uint64_t type,uint64_t offset)324 _create_dynamic_reloc(struct ld *ld, struct ld_input_section *is,
325     struct ld_symbol *lsb, uint64_t type, uint64_t offset)
326 {
327 
328 	if (lsb->lsb_bind == STB_LOCAL) {
329 		if (is->is_flags & SHF_WRITE)
330 			ld_reloc_create_entry(ld, ".rel.data.rel.local",
331 			    is, type, lsb, offset, 0);
332 		else
333 			ld_reloc_create_entry(ld, ".rel.data.rel.ro.local",
334 			    is, type, lsb, offset, 0);
335 	} else {
336 		if (is->is_flags & SHF_WRITE)
337 			ld_reloc_create_entry(ld, ".rel.data.rel",
338 			    is, type, lsb, offset, 0);
339 		else
340 			ld_reloc_create_entry(ld, ".rel.data.rel.ro",
341 			    is, type, lsb, offset, 0);
342 	}
343 
344 	if (type != R_386_RELATIVE)
345 		lsb->lsb_dynrel = 1;
346 }
347 
348 static void
_scan_reloc(struct ld * ld,struct ld_input_section * is,struct ld_reloc_entry * lre)349 _scan_reloc(struct ld *ld, struct ld_input_section *is,
350     struct ld_reloc_entry *lre)
351 {
352 	struct ld_symbol *lsb;
353 
354 	lsb = ld_symbols_ref(lre->lre_sym);
355 
356 	switch (lre->lre_type) {
357 	case R_386_NONE:
358 		break;
359 
360 	case R_386_32:
361 		/*
362 		 * For a local symbol, if te linker output a PIE or DSO,
363 		 * we should generate a R_386_RELATIVE reloc for R_386_32.
364 		 */
365 		if (lsb->lsb_bind == STB_LOCAL) {
366 			if (ld->ld_pie || ld->ld_dso)
367 				_create_dynamic_reloc(ld, is, lsb,
368 				    R_386_RELATIVE, lre->lre_offset);
369 			break;
370 		}
371 
372 		/*
373 		 * For a global symbol, we probably need to generate PLE entry
374 		 * and/ore a dynamic relocation.
375 		 *
376 		 * Note here, normally the compiler will generate a PC-relative
377 		 * relocation for function calls. However, if the code retrieve
378 		 * the address of a function and call it indirectly, assembler
379 		 * will generate absolute relocation instead. That's why we
380 		 * should check if we need to create a PLT entry here. Also, if
381 		 * we're going to create the PLT entry, we should also set the
382 		 * symbol value to the address of PLT entry just in case the
383 		 * function address is used to compare with other function
384 		 * addresses. (If PLT address is used, function will have
385 		 * unified address in the main executable and DSOs)
386 		 */
387 		if (ld_reloc_require_plt(ld, lre)) {
388 			if (!lsb->lsb_plt) {
389 				_reserve_gotplt_entry(ld, lsb);
390 				_reserve_plt_entry(ld, lsb);
391 			}
392 			/*
393 			 * Note here even if we have generated PLT for this
394 			 * function before, we still need to set this flag.
395 			 * It's possible that we first see the relative
396 			 * relocation then this absolute relocation, in
397 			 * other words, the same function can be called in
398 			 * different ways.
399 			 */
400 			lsb->lsb_func_addr = 1;
401 		}
402 
403 		if (ld_reloc_require_copy_reloc(ld, lre) &&
404 		    !lsb->lsb_copy_reloc)
405 			_create_copy_reloc(ld, lsb);
406 		else if (ld_reloc_require_dynamic_reloc(ld, lre)) {
407 			/*
408 			 * Check if we can relax R_386_32 to
409 			 * R_386_RELATIVE instead.
410 			 */
411 			if (ld_reloc_relative_relax(ld, lre))
412 				_create_dynamic_reloc(ld, is, lsb,
413 				    R_386_RELATIVE, lre->lre_offset);
414 			else
415 				_create_dynamic_reloc(ld, is, lsb,
416 				    R_386_32, lre->lre_offset);
417 		}
418 
419 		break;
420 
421 	case R_386_PLT32:
422 		/*
423 		 * In some cases we don't really need to generate a PLT
424 		 * entry, then a R_386_PLT32 relocation can be relaxed
425 		 * to a R_386_PC32 relocation.
426 		 */
427 		if (lsb->lsb_bind == STB_LOCAL ||
428 		    !ld_reloc_require_plt(ld, lre)) {
429 			lre->lre_type = R_386_PC32;
430 			break;
431 		}
432 
433 		/*
434 		 * If linker outputs an normal executable and the symbol is
435 		 * defined but is not defined inside a DSO, we can generate
436 		 * a R_386_PC32 relocation instead.
437 		 */
438 		if (ld->ld_exec && lsb->lsb_shndx != SHN_UNDEF &&
439 		    (lsb->lsb_input == NULL ||
440 		    lsb->lsb_input->li_type != LIT_DSO)) {
441 			lre->lre_type = R_386_PC32;
442 			break;
443 		}
444 
445 		/* Create an PLT entry otherwise. */
446 		if (!lsb->lsb_plt) {
447 			_reserve_gotplt_entry(ld, lsb);
448 			_reserve_plt_entry(ld, lsb);
449 		}
450 		break;
451 
452 	case R_386_PC32:
453 		/*
454 		 * When R_386_PC32 apply to a global symbol, we should
455 		 * check if we need to generate PLT entry and/or a dynamic
456 		 * relocation.
457 		 */
458 		if (lsb->lsb_bind != STB_LOCAL) {
459 			if (ld_reloc_require_plt(ld, lre) && !lsb->lsb_plt) {
460 				_reserve_gotplt_entry(ld, lsb);
461 				_reserve_plt_entry(ld, lsb);
462 			}
463 
464 			if (ld_reloc_require_copy_reloc(ld, lre) &&
465 			    !lsb->lsb_copy_reloc)
466 				_create_copy_reloc(ld, lsb);
467 			else if (ld_reloc_require_dynamic_reloc(ld, lre)) {
468 				/*
469 				 * We can not generate dynamic relocation for
470 				 * these PC-relative relocation since they
471 				 * are probably not supported by the runtime
472 				 * linkers.
473 				 */
474 				_warn_pic(ld, lre);
475 			}
476 		}
477 		break;
478 
479 	case R_386_GOTOFF:
480 	case R_386_GOTPC:
481 		/*
482 		 * These relocation types use GOT address as a base address
483 		 * and instruct the linker to build a GOT.
484 		 */
485 		(void) _find_and_create_got_section(ld, 1);
486 		break;
487 
488 	case R_386_GOT32:
489 		/*
490 		 * R_386_GOT32 relocation instructs the linker to build a
491 		 * GOT and generate a GOT entry.
492 		 */
493 		if (!lsb->lsb_got) {
494 			_reserve_got_entry(ld, lsb, 1);
495 			/*
496 			 * TODO: For now we always create a R_386_GLOB_DAT
497 			 * relocation for a GOT entry. There are cases that
498 			 * the symbol's address is known at link time and
499 			 * the GOT entry value can be filled in by the program
500 			 * linker instead.
501 			 */
502 			if (ld_reloc_require_glob_dat(ld, lre))
503 				_create_got_reloc(ld, lsb, R_386_GLOB_DAT,
504 				    lsb->lsb_got_off);
505 			else
506 				_create_got_reloc(ld, lsb, R_386_RELATIVE,
507 				    lsb->lsb_got_off);
508 		}
509 
510 	default:
511 		ld_warn(ld, "can not handle relocation %ju",
512 		    lre->lre_type);
513 		break;
514 	}
515 }
516 
517 static uint32_t
_got_offset(struct ld * ld,struct ld_symbol * lsb)518 _got_offset(struct ld *ld, struct ld_symbol *lsb)
519 {
520 	struct ld_output_section *os;
521 
522 	assert(lsb->lsb_got);
523 
524 	if (ld->ld_got == NULL) {
525 		ld->ld_got = _find_and_create_got_section(ld, 0);
526 		assert(ld->ld_got != NULL);
527 	}
528 
529 	os = ld->ld_got->is_output;
530 
531 	return (os->os_addr + ld->ld_got->is_reloff + lsb->lsb_got_off);
532 }
533 
534 static void
_process_reloc(struct ld * ld,struct ld_input_section * is,struct ld_reloc_entry * lre,struct ld_symbol * lsb,uint8_t * buf)535 _process_reloc(struct ld *ld, struct ld_input_section *is,
536     struct ld_reloc_entry *lre, struct ld_symbol *lsb, uint8_t *buf)
537 {
538 	struct ld_state *ls;
539 	struct ld_output *lo;
540 	uint32_t p, s, l, g, got;
541 	int32_t a, v;
542 
543 	ls = &ld->ld_state;
544 
545 	lo = ld->ld_output;
546 	assert(lo != NULL);
547 
548 	l = lsb->lsb_plt_off;
549 	p = lre->lre_offset + is->is_output->os_addr + is->is_reloff;
550 	got = ld->ld_got->is_output->os_addr;
551 	s = (uint32_t) lsb->lsb_value;
552 	READ_32(buf + lre->lre_offset, a);
553 
554 	switch (lre->lre_type) {
555 	case R_386_NONE:
556 		break;
557 
558 	case R_386_32:
559 		v = s + a;
560 		WRITE_32(buf + lre->lre_offset, v);
561 		break;
562 
563 	case R_386_PC32:
564 		if (lsb->lsb_plt)
565 			v = l + a - p;
566 		else
567 			v = s + a - p;
568 		WRITE_32(buf + lre->lre_offset, v);
569 		break;
570 
571 	case R_386_PLT32:
572 		if (!ls->ls_ignore_next_plt) {
573 			v = l + a - p;
574 			WRITE_32(buf + lre->lre_offset, v);
575 		} else
576 			ls->ls_ignore_next_plt = 0;
577 		break;
578 
579 	case R_386_GOT32:
580 		g = _got_offset(ld, lsb);
581 		v = g + a;
582 		WRITE_32(buf + lre->lre_offset, v);
583 		break;
584 
585 	case R_386_GOTOFF:
586 		v = s + a - got;
587 		WRITE_32(buf + lre->lre_offset, v);
588 		break;
589 
590 	case R_386_GOTPC:
591 		v = got + a - p;
592 		WRITE_32(buf + lre->lre_offset, v);
593 		break;
594 
595 	default:
596 		ld_fatal(ld, "Relocation %d not supported", lre->lre_type);
597 		break;
598 	}
599 }
600 
601 void
i386_register(struct ld * ld)602 i386_register(struct ld *ld)
603 {
604 	struct ld_arch *i386_arch;
605 
606 	if ((i386_arch = calloc(1, sizeof(*i386_arch))) == NULL)
607 		ld_fatal_std(ld, "calloc");
608 
609 	snprintf(i386_arch->name, sizeof(i386_arch->name), "%s", "i386");
610 
611 	i386_arch->script = i386_script;
612 	i386_arch->get_max_page_size = _get_max_page_size;
613 	i386_arch->get_common_page_size = _get_common_page_size;
614 	i386_arch->scan_reloc = _scan_reloc;
615 	i386_arch->process_reloc = _process_reloc;
616 	i386_arch->is_absolute_reloc = _is_absolute_reloc;
617 	i386_arch->is_relative_reloc = _is_relative_reloc;
618 	i386_arch->reloc_is_64bit = 0;
619 	i386_arch->reloc_is_rela = 0;
620 	i386_arch->reloc_entsize = sizeof(Elf32_Rel);
621 
622 	HASH_ADD_STR(ld->ld_arch_list, name, i386_arch);
623 }
624