Merge lp:~lqs/ubuntu/precise/tcc/tcc-fix-mmap-leak into lp:ubuntu/precise/tcc

Proposed by Qishuai Liu
Status: Work in progress
Proposed branch: lp:~lqs/ubuntu/precise/tcc/tcc-fix-mmap-leak
Merge into: lp:ubuntu/precise/tcc
Diff against target: 34400 lines
To merge this branch: bzr merge lp:~lqs/ubuntu/precise/tcc/tcc-fix-mmap-leak
Reviewer Review Type Date Requested Status
James Page Needs Fixing
Ubuntu branches Pending
Review via email: mp+134058@code.launchpad.net
To post a comment you must log in.
Revision history for this message
James Page (james-page) wrote :

Hi Liu

Thanks for preparing this merge proposal.

In order to update versions of packages in released versions of Ubuntu, updates must follow the Ubuntu Stable Release Update process as detailed here:

https://wiki.ubuntu.com/StableReleaseUpdates

This MP is an extremely large diff against the version in precise so won't be accepted; Please take some time to review the process. You will also need a bug, to have fixed it in the current development release and to have documented a testing process so that the fix can be verified once in -proposed.

Marking 'Needs Fixing' and WIP for the time being.

Thanks!

review: Needs Fixing

Unmerged revisions

26. By Qishuai Liu

Fix mmap leak when mprotect() on an existing malloc`ed area.

25. By Thomas Preud'homme

[Paul Tagliamonte]
  * Uploading Tom's fixes on his behalf. Although he's signed this upload
    (he issued a debdiff), I've prepared this upload. Fix verified on
    i386.

[Thomas Preud'homme]
  * debian/patches:
    + Fix incorrect reading of long long values on architecture with 32bits
      registers like i386 and armel (Closes: #681281).

24. By Thomas Preud'homme

* debian/patches:
  + Cherry-pick patch fixing incorrect shift result type (Closes: #679123).
* debian/control:
  + Update Vcs-Browser URL.

23. By Thomas Preud'homme

* debian/patches:
  + Disable the new callsave_test test on arm since it uses alloca which is
    not supported on arm (yet).

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.gitignore'
2--- .gitignore 2012-03-06 00:19:03 +0000
3+++ .gitignore 2012-11-13 09:46:40 +0000
4@@ -30,11 +30,20 @@
5 p2.c
6 tcctest[1234]
7 test[1234].out
8+tests/tcclib.h
9+tests/tcctest.gcc
10 .gdb_history
11 tcc.1
12 tcc.pod
13 config.h
14 config.mak
15 config.texi
16-tests
17 tags
18+.DS_Store
19+*.swp
20+lib/x86_64
21+lib/i386
22+tcc-doc.info
23+conftest*
24+tiny_libmaker
25+*.dSYM
26
27=== added file '.pc/.quilt_patches'
28--- .pc/.quilt_patches 1970-01-01 00:00:00 +0000
29+++ .pc/.quilt_patches 2012-11-13 09:46:40 +0000
30@@ -0,0 +1,1 @@
31+debian/patches
32
33=== added file '.pc/.quilt_series'
34--- .pc/.quilt_series 1970-01-01 00:00:00 +0000
35+++ .pc/.quilt_series 2012-11-13 09:46:40 +0000
36@@ -0,0 +1,1 @@
37+series
38
39=== removed directory '.pc/0001-Compile-tccasm.c-conditionally-TCC_CONFIG_ASM.patch'
40=== removed file '.pc/0001-Compile-tccasm.c-conditionally-TCC_CONFIG_ASM.patch/tccasm.c'
41--- .pc/0001-Compile-tccasm.c-conditionally-TCC_CONFIG_ASM.patch/tccasm.c 2012-03-06 00:19:03 +0000
42+++ .pc/0001-Compile-tccasm.c-conditionally-TCC_CONFIG_ASM.patch/tccasm.c 1970-01-01 00:00:00 +0000
43@@ -1,1117 +0,0 @@
44-/*
45- * GAS like assembler for TCC
46- *
47- * Copyright (c) 2001-2004 Fabrice Bellard
48- *
49- * This library is free software; you can redistribute it and/or
50- * modify it under the terms of the GNU Lesser General Public
51- * License as published by the Free Software Foundation; either
52- * version 2 of the License, or (at your option) any later version.
53- *
54- * This library is distributed in the hope that it will be useful,
55- * but WITHOUT ANY WARRANTY; without even the implied warranty of
56- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
57- * Lesser General Public License for more details.
58- *
59- * You should have received a copy of the GNU Lesser General Public
60- * License along with this library; if not, write to the Free Software
61- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
62- */
63-
64-#include "tcc.h"
65-
66-ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n)
67-{
68- char buf[64];
69- TokenSym *ts;
70-
71- snprintf(buf, sizeof(buf), "L..%u", n);
72- ts = tok_alloc(buf, strlen(buf));
73- return ts->tok;
74-}
75-
76-ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe);
77-
78-/* We do not use the C expression parser to handle symbols. Maybe the
79- C expression parser could be tweaked to do so. */
80-
81-static void asm_expr_unary(TCCState *s1, ExprValue *pe)
82-{
83- Sym *sym;
84- int op, n, label;
85- const char *p;
86-
87- switch(tok) {
88- case TOK_PPNUM:
89- p = tokc.cstr->data;
90- n = strtoul(p, (char **)&p, 0);
91- if (*p == 'b' || *p == 'f') {
92- /* backward or forward label */
93- label = asm_get_local_label_name(s1, n);
94- sym = label_find(label);
95- if (*p == 'b') {
96- /* backward : find the last corresponding defined label */
97- if (sym && sym->r == 0)
98- sym = sym->prev_tok;
99- if (!sym)
100- tcc_error("local label '%d' not found backward", n);
101- } else {
102- /* forward */
103- if (!sym || sym->r) {
104- /* if the last label is defined, then define a new one */
105- sym = label_push(&s1->asm_labels, label, 0);
106- sym->type.t = VT_STATIC | VT_VOID;
107- }
108- }
109- pe->v = 0;
110- pe->sym = sym;
111- } else if (*p == '\0') {
112- pe->v = n;
113- pe->sym = NULL;
114- } else {
115- tcc_error("invalid number syntax");
116- }
117- next();
118- break;
119- case '+':
120- next();
121- asm_expr_unary(s1, pe);
122- break;
123- case '-':
124- case '~':
125- op = tok;
126- next();
127- asm_expr_unary(s1, pe);
128- if (pe->sym)
129- tcc_error("invalid operation with label");
130- if (op == '-')
131- pe->v = -pe->v;
132- else
133- pe->v = ~pe->v;
134- break;
135- case TOK_CCHAR:
136- case TOK_LCHAR:
137- pe->v = tokc.i;
138- pe->sym = NULL;
139- next();
140- break;
141- case '(':
142- next();
143- asm_expr(s1, pe);
144- skip(')');
145- break;
146- default:
147- if (tok >= TOK_IDENT) {
148- /* label case : if the label was not found, add one */
149- sym = label_find(tok);
150- if (!sym) {
151- sym = label_push(&s1->asm_labels, tok, 0);
152- /* NOTE: by default, the symbol is global */
153- sym->type.t = VT_VOID;
154- }
155- if (sym->r == SHN_ABS) {
156- /* if absolute symbol, no need to put a symbol value */
157- pe->v = sym->jnext;
158- pe->sym = NULL;
159- } else {
160- pe->v = 0;
161- pe->sym = sym;
162- }
163- next();
164- } else {
165- tcc_error("bad expression syntax [%s]", get_tok_str(tok, &tokc));
166- }
167- break;
168- }
169-}
170-
171-static void asm_expr_prod(TCCState *s1, ExprValue *pe)
172-{
173- int op;
174- ExprValue e2;
175-
176- asm_expr_unary(s1, pe);
177- for(;;) {
178- op = tok;
179- if (op != '*' && op != '/' && op != '%' &&
180- op != TOK_SHL && op != TOK_SAR)
181- break;
182- next();
183- asm_expr_unary(s1, &e2);
184- if (pe->sym || e2.sym)
185- tcc_error("invalid operation with label");
186- switch(op) {
187- case '*':
188- pe->v *= e2.v;
189- break;
190- case '/':
191- if (e2.v == 0) {
192- div_error:
193- tcc_error("division by zero");
194- }
195- pe->v /= e2.v;
196- break;
197- case '%':
198- if (e2.v == 0)
199- goto div_error;
200- pe->v %= e2.v;
201- break;
202- case TOK_SHL:
203- pe->v <<= e2.v;
204- break;
205- default:
206- case TOK_SAR:
207- pe->v >>= e2.v;
208- break;
209- }
210- }
211-}
212-
213-static void asm_expr_logic(TCCState *s1, ExprValue *pe)
214-{
215- int op;
216- ExprValue e2;
217-
218- asm_expr_prod(s1, pe);
219- for(;;) {
220- op = tok;
221- if (op != '&' && op != '|' && op != '^')
222- break;
223- next();
224- asm_expr_prod(s1, &e2);
225- if (pe->sym || e2.sym)
226- tcc_error("invalid operation with label");
227- switch(op) {
228- case '&':
229- pe->v &= e2.v;
230- break;
231- case '|':
232- pe->v |= e2.v;
233- break;
234- default:
235- case '^':
236- pe->v ^= e2.v;
237- break;
238- }
239- }
240-}
241-
242-static inline void asm_expr_sum(TCCState *s1, ExprValue *pe)
243-{
244- int op;
245- ExprValue e2;
246-
247- asm_expr_logic(s1, pe);
248- for(;;) {
249- op = tok;
250- if (op != '+' && op != '-')
251- break;
252- next();
253- asm_expr_logic(s1, &e2);
254- if (op == '+') {
255- if (pe->sym != NULL && e2.sym != NULL)
256- goto cannot_relocate;
257- pe->v += e2.v;
258- if (pe->sym == NULL && e2.sym != NULL)
259- pe->sym = e2.sym;
260- } else {
261- pe->v -= e2.v;
262- /* NOTE: we are less powerful than gas in that case
263- because we store only one symbol in the expression */
264- if (!pe->sym && !e2.sym) {
265- /* OK */
266- } else if (pe->sym && !e2.sym) {
267- /* OK */
268- } else if (pe->sym && e2.sym) {
269- if (pe->sym == e2.sym) {
270- /* OK */
271- } else if (pe->sym->r == e2.sym->r && pe->sym->r != 0) {
272- /* we also accept defined symbols in the same section */
273- pe->v += pe->sym->jnext - e2.sym->jnext;
274- } else {
275- goto cannot_relocate;
276- }
277- pe->sym = NULL; /* same symbols can be substracted to NULL */
278- } else {
279- cannot_relocate:
280- tcc_error("invalid operation with label");
281- }
282- }
283- }
284-}
285-
286-ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe)
287-{
288- asm_expr_sum(s1, pe);
289-}
290-
291-ST_FUNC int asm_int_expr(TCCState *s1)
292-{
293- ExprValue e;
294- asm_expr(s1, &e);
295- if (e.sym)
296- expect("constant");
297- return e.v;
298-}
299-
300-/* NOTE: the same name space as C labels is used to avoid using too
301- much memory when storing labels in TokenStrings */
302-static void asm_new_label1(TCCState *s1, int label, int is_local,
303- int sh_num, int value)
304-{
305- Sym *sym;
306-
307- sym = label_find(label);
308- if (sym) {
309- if (sym->r) {
310- /* the label is already defined */
311- if (!is_local) {
312- tcc_error("assembler label '%s' already defined",
313- get_tok_str(label, NULL));
314- } else {
315- /* redefinition of local labels is possible */
316- goto new_label;
317- }
318- }
319- } else {
320- new_label:
321- sym = label_push(&s1->asm_labels, label, 0);
322- sym->type.t = VT_STATIC | VT_VOID;
323- }
324- sym->r = sh_num;
325- sym->jnext = value;
326-}
327-
328-static void asm_new_label(TCCState *s1, int label, int is_local)
329-{
330- asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind);
331-}
332-
333-static void asm_free_labels(TCCState *st)
334-{
335- Sym *s, *s1;
336- Section *sec;
337-
338- for(s = st->asm_labels; s != NULL; s = s1) {
339- s1 = s->prev;
340- /* define symbol value in object file */
341- if (s->r) {
342- if (s->r == SHN_ABS)
343- sec = SECTION_ABS;
344- else
345- sec = st->sections[s->r];
346- put_extern_sym2(s, sec, s->jnext, 0, 0);
347- }
348- /* remove label */
349- table_ident[s->v - TOK_IDENT]->sym_label = NULL;
350- sym_free(s);
351- }
352- st->asm_labels = NULL;
353-}
354-
355-static void use_section1(TCCState *s1, Section *sec)
356-{
357- cur_text_section->data_offset = ind;
358- cur_text_section = sec;
359- ind = cur_text_section->data_offset;
360-}
361-
362-static void use_section(TCCState *s1, const char *name)
363-{
364- Section *sec;
365- sec = find_section(s1, name);
366- use_section1(s1, sec);
367-}
368-
369-static void asm_parse_directive(TCCState *s1)
370-{
371- int n, offset, v, size, tok1;
372- Section *sec;
373- uint8_t *ptr;
374-
375- /* assembler directive */
376- next();
377- sec = cur_text_section;
378- switch(tok) {
379- case TOK_ASM_align:
380- case TOK_ASM_skip:
381- case TOK_ASM_space:
382- tok1 = tok;
383- next();
384- n = asm_int_expr(s1);
385- if (tok1 == TOK_ASM_align) {
386- if (n < 0 || (n & (n-1)) != 0)
387- tcc_error("alignment must be a positive power of two");
388- offset = (ind + n - 1) & -n;
389- size = offset - ind;
390- /* the section must have a compatible alignment */
391- if (sec->sh_addralign < n)
392- sec->sh_addralign = n;
393- } else {
394- size = n;
395- }
396- v = 0;
397- if (tok == ',') {
398- next();
399- v = asm_int_expr(s1);
400- }
401- zero_pad:
402- if (sec->sh_type != SHT_NOBITS) {
403- sec->data_offset = ind;
404- ptr = section_ptr_add(sec, size);
405- memset(ptr, v, size);
406- }
407- ind += size;
408- break;
409- case TOK_ASM_quad:
410- next();
411- for(;;) {
412- uint64_t vl;
413- const char *p;
414-
415- p = tokc.cstr->data;
416- if (tok != TOK_PPNUM) {
417- error_constant:
418- tcc_error("64 bit constant");
419- }
420- vl = strtoll(p, (char **)&p, 0);
421- if (*p != '\0')
422- goto error_constant;
423- next();
424- if (sec->sh_type != SHT_NOBITS) {
425- /* XXX: endianness */
426- gen_le32(vl);
427- gen_le32(vl >> 32);
428- } else {
429- ind += 8;
430- }
431- if (tok != ',')
432- break;
433- next();
434- }
435- break;
436- case TOK_ASM_byte:
437- size = 1;
438- goto asm_data;
439- case TOK_ASM_word:
440- case TOK_SHORT:
441- size = 2;
442- goto asm_data;
443- case TOK_LONG:
444- case TOK_INT:
445- size = 4;
446- asm_data:
447- next();
448- for(;;) {
449- ExprValue e;
450- asm_expr(s1, &e);
451- if (sec->sh_type != SHT_NOBITS) {
452- if (size == 4) {
453- gen_expr32(&e);
454- } else {
455- if (e.sym)
456- expect("constant");
457- if (size == 1)
458- g(e.v);
459- else
460- gen_le16(e.v);
461- }
462- } else {
463- ind += size;
464- }
465- if (tok != ',')
466- break;
467- next();
468- }
469- break;
470- case TOK_ASM_fill:
471- {
472- int repeat, size, val, i, j;
473- uint8_t repeat_buf[8];
474- next();
475- repeat = asm_int_expr(s1);
476- if (repeat < 0) {
477- tcc_error("repeat < 0; .fill ignored");
478- break;
479- }
480- size = 1;
481- val = 0;
482- if (tok == ',') {
483- next();
484- size = asm_int_expr(s1);
485- if (size < 0) {
486- tcc_error("size < 0; .fill ignored");
487- break;
488- }
489- if (size > 8)
490- size = 8;
491- if (tok == ',') {
492- next();
493- val = asm_int_expr(s1);
494- }
495- }
496- /* XXX: endianness */
497- repeat_buf[0] = val;
498- repeat_buf[1] = val >> 8;
499- repeat_buf[2] = val >> 16;
500- repeat_buf[3] = val >> 24;
501- repeat_buf[4] = 0;
502- repeat_buf[5] = 0;
503- repeat_buf[6] = 0;
504- repeat_buf[7] = 0;
505- for(i = 0; i < repeat; i++) {
506- for(j = 0; j < size; j++) {
507- g(repeat_buf[j]);
508- }
509- }
510- }
511- break;
512- case TOK_ASM_org:
513- {
514- unsigned long n;
515- next();
516- /* XXX: handle section symbols too */
517- n = asm_int_expr(s1);
518- if (n < ind)
519- tcc_error("attempt to .org backwards");
520- v = 0;
521- size = n - ind;
522- goto zero_pad;
523- }
524- break;
525- case TOK_ASM_globl:
526- case TOK_ASM_global:
527- case TOK_ASM_weak:
528- tok1 = tok;
529- do {
530- Sym *sym;
531-
532- next();
533- sym = label_find(tok);
534- if (!sym) {
535- sym = label_push(&s1->asm_labels, tok, 0);
536- sym->type.t = VT_VOID;
537- }
538- sym->type.t &= ~VT_STATIC;
539- if (tok1 == TOK_ASM_weak)
540- sym->type.t |= VT_WEAK;
541- next();
542- } while (tok == ',');
543- break;
544- case TOK_ASM_string:
545- case TOK_ASM_ascii:
546- case TOK_ASM_asciz:
547- {
548- const uint8_t *p;
549- int i, size, t;
550-
551- t = tok;
552- next();
553- for(;;) {
554- if (tok != TOK_STR)
555- expect("string constant");
556- p = tokc.cstr->data;
557- size = tokc.cstr->size;
558- if (t == TOK_ASM_ascii && size > 0)
559- size--;
560- for(i = 0; i < size; i++)
561- g(p[i]);
562- next();
563- if (tok == ',') {
564- next();
565- } else if (tok != TOK_STR) {
566- break;
567- }
568- }
569- }
570- break;
571- case TOK_ASM_text:
572- case TOK_ASM_data:
573- case TOK_ASM_bss:
574- {
575- char sname[64];
576- tok1 = tok;
577- n = 0;
578- next();
579- if (tok != ';' && tok != TOK_LINEFEED) {
580- n = asm_int_expr(s1);
581- next();
582- }
583- sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n);
584- use_section(s1, sname);
585- }
586- break;
587- case TOK_ASM_file:
588- {
589- char filename[512];
590-
591- filename[0] = '\0';
592- next();
593-
594- if (tok == TOK_STR)
595- pstrcat(filename, sizeof(filename), tokc.cstr->data);
596- else
597- pstrcat(filename, sizeof(filename), get_tok_str(tok, NULL));
598-
599- if (s1->warn_unsupported)
600- tcc_warning("ignoring .file %s", filename);
601-
602- next();
603- }
604- break;
605- case TOK_ASM_ident:
606- {
607- char ident[256];
608-
609- ident[0] = '\0';
610- next();
611-
612- if (tok == TOK_STR)
613- pstrcat(ident, sizeof(ident), tokc.cstr->data);
614- else
615- pstrcat(ident, sizeof(ident), get_tok_str(tok, NULL));
616-
617- if (s1->warn_unsupported)
618- tcc_warning("ignoring .ident %s", ident);
619-
620- next();
621- }
622- break;
623- case TOK_ASM_size:
624- {
625- Sym *sym;
626-
627- next();
628- sym = label_find(tok);
629- if (!sym) {
630- tcc_error("label not found: %s", get_tok_str(tok, NULL));
631- }
632-
633- next();
634- skip(',');
635- /* XXX .size name,label2-label1 */
636- if (s1->warn_unsupported)
637- tcc_warning("ignoring .size %s,*", get_tok_str(tok, NULL));
638-
639- while (tok != '\n' && tok != CH_EOF) {
640- next();
641- }
642- }
643- break;
644- case TOK_ASM_type:
645- {
646- Sym *sym;
647- const char *newtype;
648-
649- next();
650- sym = label_find(tok);
651- if (!sym) {
652- sym = label_push(&s1->asm_labels, tok, 0);
653- sym->type.t = VT_VOID;
654- }
655-
656- next();
657- skip(',');
658- if (tok == TOK_STR) {
659- newtype = tokc.cstr->data;
660- } else {
661- if (tok == '@' || tok == '%')
662- skip(tok);
663- newtype = get_tok_str(tok, NULL);
664- }
665-
666- if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) {
667- sym->type.t = VT_FUNC;
668- }
669- else if (s1->warn_unsupported)
670- tcc_warning("change type of '%s' from 0x%x to '%s' ignored",
671- get_tok_str(sym->v, NULL), sym->type.t, newtype);
672-
673- next();
674- }
675- break;
676- case TOK_SECTION1:
677- {
678- char sname[256];
679-
680- /* XXX: support more options */
681- next();
682- sname[0] = '\0';
683- while (tok != ';' && tok != TOK_LINEFEED && tok != ',') {
684- if (tok == TOK_STR)
685- pstrcat(sname, sizeof(sname), tokc.cstr->data);
686- else
687- pstrcat(sname, sizeof(sname), get_tok_str(tok, NULL));
688- next();
689- }
690- if (tok == ',') {
691- /* skip section options */
692- next();
693- if (tok != TOK_STR)
694- expect("string constant");
695- next();
696- }
697- last_text_section = cur_text_section;
698- use_section(s1, sname);
699- }
700- break;
701- case TOK_ASM_previous:
702- {
703- Section *sec;
704- next();
705- if (!last_text_section)
706- tcc_error("no previous section referenced");
707- sec = cur_text_section;
708- use_section1(s1, last_text_section);
709- last_text_section = sec;
710- }
711- break;
712-#ifdef TCC_TARGET_I386
713- case TOK_ASM_code16:
714- {
715- next();
716- s1->seg_size = 16;
717- }
718- break;
719- case TOK_ASM_code32:
720- {
721- next();
722- s1->seg_size = 32;
723- }
724- break;
725-#endif
726-#ifdef TCC_TARGET_X86_64
727- /* added for compatibility with GAS */
728- case TOK_ASM_code64:
729- next();
730- break;
731-#endif
732- default:
733- tcc_error("unknown assembler directive '.%s'", get_tok_str(tok, NULL));
734- break;
735- }
736-}
737-
738-
739-/* assemble a file */
740-static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
741-{
742- int opcode;
743-
744-#if 0
745- /* print stats about opcodes */
746- {
747- const ASMInstr *pa;
748- int freq[4];
749- int op_vals[500];
750- int nb_op_vals, i, j;
751-
752- nb_op_vals = 0;
753- memset(freq, 0, sizeof(freq));
754- for(pa = asm_instrs; pa->sym != 0; pa++) {
755- freq[pa->nb_ops]++;
756- for(i=0;i<pa->nb_ops;i++) {
757- for(j=0;j<nb_op_vals;j++) {
758- if (pa->op_type[i] == op_vals[j])
759- goto found;
760- }
761- op_vals[nb_op_vals++] = pa->op_type[i];
762- found: ;
763- }
764- }
765- for(i=0;i<nb_op_vals;i++) {
766- int v = op_vals[i];
767- if ((v & (v - 1)) != 0)
768- printf("%3d: %08x\n", i, v);
769- }
770- printf("size=%d nb=%d f0=%d f1=%d f2=%d f3=%d\n",
771- sizeof(asm_instrs), sizeof(asm_instrs) / sizeof(ASMInstr),
772- freq[0], freq[1], freq[2], freq[3]);
773- }
774-#endif
775-
776- /* XXX: undefine C labels */
777-
778- ch = file->buf_ptr[0];
779- tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
780- parse_flags = PARSE_FLAG_ASM_COMMENTS;
781- if (do_preprocess)
782- parse_flags |= PARSE_FLAG_PREPROCESS;
783- next();
784- for(;;) {
785- if (tok == TOK_EOF)
786- break;
787- parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
788- redo:
789- if (tok == '#') {
790- /* horrible gas comment */
791- while (tok != TOK_LINEFEED)
792- next();
793- } else if (tok == '.') {
794- asm_parse_directive(s1);
795- } else if (tok == TOK_PPNUM) {
796- const char *p;
797- int n;
798- p = tokc.cstr->data;
799- n = strtoul(p, (char **)&p, 10);
800- if (*p != '\0')
801- expect("':'");
802- /* new local label */
803- asm_new_label(s1, asm_get_local_label_name(s1, n), 1);
804- next();
805- skip(':');
806- goto redo;
807- } else if (tok >= TOK_IDENT) {
808- /* instruction or label */
809- opcode = tok;
810- next();
811- if (tok == ':') {
812- /* new label */
813- asm_new_label(s1, opcode, 0);
814- next();
815- goto redo;
816- } else if (tok == '=') {
817- int n;
818- next();
819- n = asm_int_expr(s1);
820- asm_new_label1(s1, opcode, 0, SHN_ABS, n);
821- goto redo;
822- } else {
823- asm_opcode(s1, opcode);
824- }
825- }
826- /* end of line */
827- if (tok != ';' && tok != TOK_LINEFEED){
828- expect("end of line");
829- }
830- parse_flags &= ~PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
831- next();
832- }
833-
834- asm_free_labels(s1);
835-
836- return 0;
837-}
838-
839-/* Assemble the current file */
840-ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
841-{
842- Sym *define_start;
843- int ret;
844-
845- preprocess_init(s1);
846-
847- /* default section is text */
848- cur_text_section = text_section;
849- ind = cur_text_section->data_offset;
850-
851- define_start = define_stack;
852-
853- /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
854- symbols can be safely used */
855- put_elf_sym(symtab_section, 0, 0,
856- ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
857- SHN_ABS, file->filename);
858-
859- ret = tcc_assemble_internal(s1, do_preprocess);
860-
861- cur_text_section->data_offset = ind;
862-
863- free_defines(define_start);
864-
865- return ret;
866-}
867-
868-/********************************************************************/
869-/* GCC inline asm support */
870-
871-/* assemble the string 'str' in the current C compilation unit without
872- C preprocessing. NOTE: str is modified by modifying the '\0' at the
873- end */
874-static void tcc_assemble_inline(TCCState *s1, char *str, int len)
875-{
876- int saved_parse_flags;
877- const int *saved_macro_ptr;
878-
879- saved_parse_flags = parse_flags;
880- saved_macro_ptr = macro_ptr;
881-
882- tcc_open_bf(s1, file->filename, len);
883- file->line_num = file->prev->line_num;
884- memcpy(file->buffer, str, len);
885-
886- macro_ptr = NULL;
887- tcc_assemble_internal(s1, 0);
888- tcc_close();
889-
890- parse_flags = saved_parse_flags;
891- macro_ptr = saved_macro_ptr;
892-}
893-
894-/* find a constraint by its number or id (gcc 3 extended
895- syntax). return -1 if not found. Return in *pp in char after the
896- constraint */
897-ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands,
898- const char *name, const char **pp)
899-{
900- int index;
901- TokenSym *ts;
902- const char *p;
903-
904- if (isnum(*name)) {
905- index = 0;
906- while (isnum(*name)) {
907- index = (index * 10) + (*name) - '0';
908- name++;
909- }
910- if ((unsigned)index >= nb_operands)
911- index = -1;
912- } else if (*name == '[') {
913- name++;
914- p = strchr(name, ']');
915- if (p) {
916- ts = tok_alloc(name, p - name);
917- for(index = 0; index < nb_operands; index++) {
918- if (operands[index].id == ts->tok)
919- goto found;
920- }
921- index = -1;
922- found:
923- name = p + 1;
924- } else {
925- index = -1;
926- }
927- } else {
928- index = -1;
929- }
930- if (pp)
931- *pp = name;
932- return index;
933-}
934-
935-static void subst_asm_operands(ASMOperand *operands, int nb_operands,
936- int nb_outputs,
937- CString *out_str, CString *in_str)
938-{
939- int c, index, modifier;
940- const char *str;
941- ASMOperand *op;
942- SValue sv;
943-
944- cstr_new(out_str);
945- str = in_str->data;
946- for(;;) {
947- c = *str++;
948- if (c == '%') {
949- if (*str == '%') {
950- str++;
951- goto add_char;
952- }
953- modifier = 0;
954- if (*str == 'c' || *str == 'n' ||
955- *str == 'b' || *str == 'w' || *str == 'h')
956- modifier = *str++;
957- index = find_constraint(operands, nb_operands, str, &str);
958- if (index < 0)
959- tcc_error("invalid operand reference after %%");
960- op = &operands[index];
961- sv = *op->vt;
962- if (op->reg >= 0) {
963- sv.r = op->reg;
964- if ((op->vt->r & VT_VALMASK) == VT_LLOCAL && op->is_memory)
965- sv.r |= VT_LVAL;
966- }
967- subst_asm_operand(out_str, &sv, modifier);
968- } else {
969- add_char:
970- cstr_ccat(out_str, c);
971- if (c == '\0')
972- break;
973- }
974- }
975-}
976-
977-
978-static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
979- int is_output)
980-{
981- ASMOperand *op;
982- int nb_operands;
983-
984- if (tok != ':') {
985- nb_operands = *nb_operands_ptr;
986- for(;;) {
987- if (nb_operands >= MAX_ASM_OPERANDS)
988- tcc_error("too many asm operands");
989- op = &operands[nb_operands++];
990- op->id = 0;
991- if (tok == '[') {
992- next();
993- if (tok < TOK_IDENT)
994- expect("identifier");
995- op->id = tok;
996- next();
997- skip(']');
998- }
999- if (tok != TOK_STR)
1000- expect("string constant");
1001- op->constraint = tcc_malloc(tokc.cstr->size);
1002- strcpy(op->constraint, tokc.cstr->data);
1003- next();
1004- skip('(');
1005- gexpr();
1006- if (is_output) {
1007- test_lvalue();
1008- } else {
1009- /* we want to avoid LLOCAL case, except when the 'm'
1010- constraint is used. Note that it may come from
1011- register storage, so we need to convert (reg)
1012- case */
1013- if ((vtop->r & VT_LVAL) &&
1014- ((vtop->r & VT_VALMASK) == VT_LLOCAL ||
1015- (vtop->r & VT_VALMASK) < VT_CONST) &&
1016- !strchr(op->constraint, 'm')) {
1017- gv(RC_INT);
1018- }
1019- }
1020- op->vt = vtop;
1021- skip(')');
1022- if (tok == ',') {
1023- next();
1024- } else {
1025- break;
1026- }
1027- }
1028- *nb_operands_ptr = nb_operands;
1029- }
1030-}
1031-
1032-/* parse the GCC asm() instruction */
1033-ST_FUNC void asm_instr(void)
1034-{
1035- CString astr, astr1;
1036- ASMOperand operands[MAX_ASM_OPERANDS];
1037- int nb_outputs, nb_operands, i, must_subst, out_reg;
1038- uint8_t clobber_regs[NB_ASM_REGS];
1039-
1040- next();
1041- /* since we always generate the asm() instruction, we can ignore
1042- volatile */
1043- if (tok == TOK_VOLATILE1 || tok == TOK_VOLATILE2 || tok == TOK_VOLATILE3) {
1044- next();
1045- }
1046- parse_asm_str(&astr);
1047- nb_operands = 0;
1048- nb_outputs = 0;
1049- must_subst = 0;
1050- memset(clobber_regs, 0, sizeof(clobber_regs));
1051- if (tok == ':') {
1052- next();
1053- must_subst = 1;
1054- /* output args */
1055- parse_asm_operands(operands, &nb_operands, 1);
1056- nb_outputs = nb_operands;
1057- if (tok == ':') {
1058- next();
1059- if (tok != ')') {
1060- /* input args */
1061- parse_asm_operands(operands, &nb_operands, 0);
1062- if (tok == ':') {
1063- /* clobber list */
1064- /* XXX: handle registers */
1065- next();
1066- for(;;) {
1067- if (tok != TOK_STR)
1068- expect("string constant");
1069- asm_clobber(clobber_regs, tokc.cstr->data);
1070- next();
1071- if (tok == ',') {
1072- next();
1073- } else {
1074- break;
1075- }
1076- }
1077- }
1078- }
1079- }
1080- }
1081- skip(')');
1082- /* NOTE: we do not eat the ';' so that we can restore the current
1083- token after the assembler parsing */
1084- if (tok != ';')
1085- expect("';'");
1086-
1087- /* save all values in the memory */
1088- save_regs(0);
1089-
1090- /* compute constraints */
1091- asm_compute_constraints(operands, nb_operands, nb_outputs,
1092- clobber_regs, &out_reg);
1093-
1094- /* substitute the operands in the asm string. No substitution is
1095- done if no operands (GCC behaviour) */
1096-#ifdef ASM_DEBUG
1097- printf("asm: \"%s\"\n", (char *)astr.data);
1098-#endif
1099- if (must_subst) {
1100- subst_asm_operands(operands, nb_operands, nb_outputs, &astr1, &astr);
1101- cstr_free(&astr);
1102- } else {
1103- astr1 = astr;
1104- }
1105-#ifdef ASM_DEBUG
1106- printf("subst_asm: \"%s\"\n", (char *)astr1.data);
1107-#endif
1108-
1109- /* generate loads */
1110- asm_gen_code(operands, nb_operands, nb_outputs, 0,
1111- clobber_regs, out_reg);
1112-
1113- /* assemble the string with tcc internal assembler */
1114- tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1);
1115-
1116- /* restore the current C token */
1117- next();
1118-
1119- /* store the output values if needed */
1120- asm_gen_code(operands, nb_operands, nb_outputs, 1,
1121- clobber_regs, out_reg);
1122-
1123- /* free everything */
1124- for(i=0;i<nb_operands;i++) {
1125- ASMOperand *op;
1126- op = &operands[i];
1127- tcc_free(op->constraint);
1128- vpop();
1129- }
1130- cstr_free(&astr1);
1131-}
1132-
1133-ST_FUNC void asm_global_instr(void)
1134-{
1135- CString astr;
1136-
1137- next();
1138- parse_asm_str(&astr);
1139- skip(')');
1140- /* NOTE: we do not eat the ';' so that we can restore the current
1141- token after the assembler parsing */
1142- if (tok != ';')
1143- expect("';'");
1144-
1145-#ifdef ASM_DEBUG
1146- printf("asm_global: \"%s\"\n", (char *)astr.data);
1147-#endif
1148- cur_text_section = text_section;
1149- ind = cur_text_section->data_offset;
1150-
1151- /* assemble the string with tcc internal assembler */
1152- tcc_assemble_inline(tcc_state, astr.data, astr.size - 1);
1153-
1154- cur_text_section->data_offset = ind;
1155-
1156- /* restore the current C token */
1157- next();
1158-
1159- cstr_free(&astr);
1160-}
1161
1162=== added directory '.pc/0001-Fix-R_ARM_REL32-relocation.patch'
1163=== added file '.pc/0001-Fix-R_ARM_REL32-relocation.patch/tccelf.c'
1164--- .pc/0001-Fix-R_ARM_REL32-relocation.patch/tccelf.c 1970-01-01 00:00:00 +0000
1165+++ .pc/0001-Fix-R_ARM_REL32-relocation.patch/tccelf.c 2012-11-13 09:46:40 +0000
1166@@ -0,0 +1,2995 @@
1167+/*
1168+ * ELF file handling for TCC
1169+ *
1170+ * Copyright (c) 2001-2004 Fabrice Bellard
1171+ *
1172+ * This library is free software; you can redistribute it and/or
1173+ * modify it under the terms of the GNU Lesser General Public
1174+ * License as published by the Free Software Foundation; either
1175+ * version 2 of the License, or (at your option) any later version.
1176+ *
1177+ * This library is distributed in the hope that it will be useful,
1178+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1179+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1180+ * Lesser General Public License for more details.
1181+ *
1182+ * You should have received a copy of the GNU Lesser General Public
1183+ * License along with this library; if not, write to the Free Software
1184+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1185+ */
1186+
1187+#include "tcc.h"
1188+
1189+static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
1190+
1191+ST_FUNC int put_elf_str(Section *s, const char *sym)
1192+{
1193+ int offset, len;
1194+ char *ptr;
1195+
1196+ len = strlen(sym) + 1;
1197+ offset = s->data_offset;
1198+ ptr = section_ptr_add(s, len);
1199+ memcpy(ptr, sym, len);
1200+ return offset;
1201+}
1202+
1203+/* elf symbol hashing function */
1204+static unsigned long elf_hash(const unsigned char *name)
1205+{
1206+ unsigned long h = 0, g;
1207+
1208+ while (*name) {
1209+ h = (h << 4) + *name++;
1210+ g = h & 0xf0000000;
1211+ if (g)
1212+ h ^= g >> 24;
1213+ h &= ~g;
1214+ }
1215+ return h;
1216+}
1217+
1218+/* rebuild hash table of section s */
1219+/* NOTE: we do factorize the hash table code to go faster */
1220+static void rebuild_hash(Section *s, unsigned int nb_buckets)
1221+{
1222+ ElfW(Sym) *sym;
1223+ int *ptr, *hash, nb_syms, sym_index, h;
1224+ char *strtab;
1225+
1226+ strtab = s->link->data;
1227+ nb_syms = s->data_offset / sizeof(ElfW(Sym));
1228+
1229+ s->hash->data_offset = 0;
1230+ ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
1231+ ptr[0] = nb_buckets;
1232+ ptr[1] = nb_syms;
1233+ ptr += 2;
1234+ hash = ptr;
1235+ memset(hash, 0, (nb_buckets + 1) * sizeof(int));
1236+ ptr += nb_buckets + 1;
1237+
1238+ sym = (ElfW(Sym) *)s->data + 1;
1239+ for(sym_index = 1; sym_index < nb_syms; sym_index++) {
1240+ if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1241+ h = elf_hash(strtab + sym->st_name) % nb_buckets;
1242+ *ptr = hash[h];
1243+ hash[h] = sym_index;
1244+ } else {
1245+ *ptr = 0;
1246+ }
1247+ ptr++;
1248+ sym++;
1249+ }
1250+}
1251+
1252+/* return the symbol number */
1253+ST_FUNC int put_elf_sym(Section *s, uplong value, unsigned long size,
1254+ int info, int other, int shndx, const char *name)
1255+{
1256+ int name_offset, sym_index;
1257+ int nbuckets, h;
1258+ ElfW(Sym) *sym;
1259+ Section *hs;
1260+
1261+ sym = section_ptr_add(s, sizeof(ElfW(Sym)));
1262+ if (name)
1263+ name_offset = put_elf_str(s->link, name);
1264+ else
1265+ name_offset = 0;
1266+ /* XXX: endianness */
1267+ sym->st_name = name_offset;
1268+ sym->st_value = value;
1269+ sym->st_size = size;
1270+ sym->st_info = info;
1271+ sym->st_other = other;
1272+ sym->st_shndx = shndx;
1273+ sym_index = sym - (ElfW(Sym) *)s->data;
1274+ hs = s->hash;
1275+ if (hs) {
1276+ int *ptr, *base;
1277+ ptr = section_ptr_add(hs, sizeof(int));
1278+ base = (int *)hs->data;
1279+ /* only add global or weak symbols */
1280+ if (ELFW(ST_BIND)(info) != STB_LOCAL) {
1281+ /* add another hashing entry */
1282+ nbuckets = base[0];
1283+ h = elf_hash(name) % nbuckets;
1284+ *ptr = base[2 + h];
1285+ base[2 + h] = sym_index;
1286+ base[1]++;
1287+ /* we resize the hash table */
1288+ hs->nb_hashed_syms++;
1289+ if (hs->nb_hashed_syms > 2 * nbuckets) {
1290+ rebuild_hash(s, 2 * nbuckets);
1291+ }
1292+ } else {
1293+ *ptr = 0;
1294+ base[1]++;
1295+ }
1296+ }
1297+ return sym_index;
1298+}
1299+
1300+/* find global ELF symbol 'name' and return its index. Return 0 if not
1301+ found. */
1302+ST_FUNC int find_elf_sym(Section *s, const char *name)
1303+{
1304+ ElfW(Sym) *sym;
1305+ Section *hs;
1306+ int nbuckets, sym_index, h;
1307+ const char *name1;
1308+
1309+ hs = s->hash;
1310+ if (!hs)
1311+ return 0;
1312+ nbuckets = ((int *)hs->data)[0];
1313+ h = elf_hash(name) % nbuckets;
1314+ sym_index = ((int *)hs->data)[2 + h];
1315+ while (sym_index != 0) {
1316+ sym = &((ElfW(Sym) *)s->data)[sym_index];
1317+ name1 = s->link->data + sym->st_name;
1318+ if (!strcmp(name, name1))
1319+ return sym_index;
1320+ sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
1321+ }
1322+ return 0;
1323+}
1324+
1325+/* return elf symbol value, signal error if 'err' is nonzero */
1326+static void *get_elf_sym_addr(TCCState *s, const char *name, int err)
1327+{
1328+ int sym_index;
1329+ ElfW(Sym) *sym;
1330+
1331+ sym_index = find_elf_sym(s->symtab, name);
1332+ sym = &((ElfW(Sym) *)s->symtab->data)[sym_index];
1333+ if (!sym_index || sym->st_shndx == SHN_UNDEF) {
1334+ if (err)
1335+ tcc_error("%s not defined", name);
1336+ return NULL;
1337+ }
1338+ return (void*)(uplong)sym->st_value;
1339+}
1340+
1341+/* return elf symbol value */
1342+LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
1343+{
1344+ return get_elf_sym_addr(s, name, 0);
1345+}
1346+
1347+/* return elf symbol value or error */
1348+ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name)
1349+{
1350+ return get_elf_sym_addr(s, name, 1);
1351+}
1352+
1353+/* add an elf symbol : check if it is already defined and patch
1354+ it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
1355+ST_FUNC int add_elf_sym(Section *s, uplong value, unsigned long size,
1356+ int info, int other, int sh_num, const char *name)
1357+{
1358+ ElfW(Sym) *esym;
1359+ int sym_bind, sym_index, sym_type, esym_bind;
1360+ unsigned char sym_vis, esym_vis, new_vis;
1361+
1362+ sym_bind = ELFW(ST_BIND)(info);
1363+ sym_type = ELFW(ST_TYPE)(info);
1364+ sym_vis = ELFW(ST_VISIBILITY)(other);
1365+
1366+ if (sym_bind != STB_LOCAL) {
1367+ /* we search global or weak symbols */
1368+ sym_index = find_elf_sym(s, name);
1369+ if (!sym_index)
1370+ goto do_def;
1371+ esym = &((ElfW(Sym) *)s->data)[sym_index];
1372+ if (esym->st_shndx != SHN_UNDEF) {
1373+ esym_bind = ELFW(ST_BIND)(esym->st_info);
1374+ /* propagate the most constraining visibility */
1375+ /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
1376+ esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
1377+ if (esym_vis == STV_DEFAULT) {
1378+ new_vis = sym_vis;
1379+ } else if (sym_vis == STV_DEFAULT) {
1380+ new_vis = esym_vis;
1381+ } else {
1382+ new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
1383+ }
1384+ esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
1385+ | new_vis;
1386+ other = esym->st_other; /* in case we have to patch esym */
1387+ if (sh_num == SHN_UNDEF) {
1388+ /* ignore adding of undefined symbol if the
1389+ corresponding symbol is already defined */
1390+ } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
1391+ /* global overrides weak, so patch */
1392+ goto do_patch;
1393+ } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
1394+ /* weak is ignored if already global */
1395+ } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
1396+ /* keep first-found weak definition, ignore subsequents */
1397+ } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
1398+ /* ignore hidden symbols after */
1399+ } else if (esym->st_shndx == SHN_COMMON
1400+ && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
1401+ /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
1402+ No idea if this is the correct solution ... */
1403+ goto do_patch;
1404+ } else if (s == tcc_state->dynsymtab_section) {
1405+ /* we accept that two DLL define the same symbol */
1406+ } else {
1407+#if 1
1408+ printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
1409+ sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
1410+#endif
1411+ tcc_error_noabort("'%s' defined twice", name);
1412+ }
1413+ } else {
1414+ do_patch:
1415+ esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
1416+ esym->st_shndx = sh_num;
1417+ new_undef_sym = 1;
1418+ esym->st_value = value;
1419+ esym->st_size = size;
1420+ esym->st_other = other;
1421+ }
1422+ } else {
1423+ do_def:
1424+ sym_index = put_elf_sym(s, value, size,
1425+ ELFW(ST_INFO)(sym_bind, sym_type), other,
1426+ sh_num, name);
1427+ }
1428+ return sym_index;
1429+}
1430+
1431+/* put relocation */
1432+ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
1433+ int type, int symbol)
1434+{
1435+ char buf[256];
1436+ Section *sr;
1437+ ElfW_Rel *rel;
1438+
1439+ sr = s->reloc;
1440+ if (!sr) {
1441+ /* if no relocation section, create it */
1442+ snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
1443+ /* if the symtab is allocated, then we consider the relocation
1444+ are also */
1445+ sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
1446+ sr->sh_entsize = sizeof(ElfW_Rel);
1447+ sr->link = symtab;
1448+ sr->sh_info = s->sh_num;
1449+ s->reloc = sr;
1450+ }
1451+ rel = section_ptr_add(sr, sizeof(ElfW_Rel));
1452+ rel->r_offset = offset;
1453+ rel->r_info = ELFW(R_INFO)(symbol, type);
1454+#ifdef TCC_TARGET_X86_64
1455+ rel->r_addend = 0;
1456+#endif
1457+}
1458+
1459+/* put stab debug information */
1460+
1461+ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
1462+ unsigned long value)
1463+{
1464+ Stab_Sym *sym;
1465+
1466+ sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
1467+ if (str) {
1468+ sym->n_strx = put_elf_str(stabstr_section, str);
1469+ } else {
1470+ sym->n_strx = 0;
1471+ }
1472+ sym->n_type = type;
1473+ sym->n_other = other;
1474+ sym->n_desc = desc;
1475+ sym->n_value = value;
1476+}
1477+
1478+ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
1479+ unsigned long value, Section *sec, int sym_index)
1480+{
1481+ put_stabs(str, type, other, desc, value);
1482+ put_elf_reloc(symtab_section, stab_section,
1483+ stab_section->data_offset - sizeof(unsigned int),
1484+ R_DATA_32, sym_index);
1485+}
1486+
1487+ST_FUNC void put_stabn(int type, int other, int desc, int value)
1488+{
1489+ put_stabs(NULL, type, other, desc, value);
1490+}
1491+
1492+ST_FUNC void put_stabd(int type, int other, int desc)
1493+{
1494+ put_stabs(NULL, type, other, desc, 0);
1495+}
1496+
1497+/* In an ELF file symbol table, the local symbols must appear below
1498+ the global and weak ones. Since TCC cannot sort it while generating
1499+ the code, we must do it after. All the relocation tables are also
1500+ modified to take into account the symbol table sorting */
1501+static void sort_syms(TCCState *s1, Section *s)
1502+{
1503+ int *old_to_new_syms;
1504+ ElfW(Sym) *new_syms;
1505+ int nb_syms, i;
1506+ ElfW(Sym) *p, *q;
1507+ ElfW_Rel *rel, *rel_end;
1508+ Section *sr;
1509+ int type, sym_index;
1510+
1511+ nb_syms = s->data_offset / sizeof(ElfW(Sym));
1512+ new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
1513+ old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
1514+
1515+ /* first pass for local symbols */
1516+ p = (ElfW(Sym) *)s->data;
1517+ q = new_syms;
1518+ for(i = 0; i < nb_syms; i++) {
1519+ if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
1520+ old_to_new_syms[i] = q - new_syms;
1521+ *q++ = *p;
1522+ }
1523+ p++;
1524+ }
1525+ /* save the number of local symbols in section header */
1526+ s->sh_info = q - new_syms;
1527+
1528+ /* then second pass for non local symbols */
1529+ p = (ElfW(Sym) *)s->data;
1530+ for(i = 0; i < nb_syms; i++) {
1531+ if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
1532+ old_to_new_syms[i] = q - new_syms;
1533+ *q++ = *p;
1534+ }
1535+ p++;
1536+ }
1537+
1538+ /* we copy the new symbols to the old */
1539+ memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
1540+ tcc_free(new_syms);
1541+
1542+ /* now we modify all the relocations */
1543+ for(i = 1; i < s1->nb_sections; i++) {
1544+ sr = s1->sections[i];
1545+ if (sr->sh_type == SHT_RELX && sr->link == s) {
1546+ rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
1547+ for(rel = (ElfW_Rel *)sr->data;
1548+ rel < rel_end;
1549+ rel++) {
1550+ sym_index = ELFW(R_SYM)(rel->r_info);
1551+ type = ELFW(R_TYPE)(rel->r_info);
1552+ sym_index = old_to_new_syms[sym_index];
1553+ rel->r_info = ELFW(R_INFO)(sym_index, type);
1554+ }
1555+ }
1556+ }
1557+
1558+ tcc_free(old_to_new_syms);
1559+}
1560+
1561+/* relocate common symbols in the .bss section */
1562+ST_FUNC void relocate_common_syms(void)
1563+{
1564+ ElfW(Sym) *sym, *sym_end;
1565+ unsigned long offset, align;
1566+
1567+ sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
1568+ for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1569+ sym < sym_end;
1570+ sym++) {
1571+ if (sym->st_shndx == SHN_COMMON) {
1572+ /* align symbol */
1573+ align = sym->st_value;
1574+ offset = bss_section->data_offset;
1575+ offset = (offset + align - 1) & -align;
1576+ sym->st_value = offset;
1577+ sym->st_shndx = bss_section->sh_num;
1578+ offset += sym->st_size;
1579+ bss_section->data_offset = offset;
1580+ }
1581+ }
1582+}
1583+
1584+/* relocate symbol table, resolve undefined symbols if do_resolve is
1585+ true and output error if undefined symbol. */
1586+ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
1587+{
1588+ ElfW(Sym) *sym, *esym, *sym_end;
1589+ int sym_bind, sh_num, sym_index;
1590+ const char *name;
1591+
1592+ sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
1593+ for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1594+ sym < sym_end;
1595+ sym++) {
1596+ sh_num = sym->st_shndx;
1597+ if (sh_num == SHN_UNDEF) {
1598+ name = strtab_section->data + sym->st_name;
1599+ if (do_resolve) {
1600+#if !defined TCC_TARGET_PE || !defined _WIN32
1601+ void *addr;
1602+ name = symtab_section->link->data + sym->st_name;
1603+ addr = resolve_sym(s1, name);
1604+ if (addr) {
1605+ sym->st_value = (uplong)addr;
1606+ goto found;
1607+ }
1608+#endif
1609+ } else if (s1->dynsym) {
1610+ /* if dynamic symbol exist, then use it */
1611+ sym_index = find_elf_sym(s1->dynsym, name);
1612+ if (sym_index) {
1613+ esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
1614+ sym->st_value = esym->st_value;
1615+ goto found;
1616+ }
1617+ }
1618+ /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1619+ it */
1620+ if (!strcmp(name, "_fp_hw"))
1621+ goto found;
1622+ /* only weak symbols are accepted to be undefined. Their
1623+ value is zero */
1624+ sym_bind = ELFW(ST_BIND)(sym->st_info);
1625+ if (sym_bind == STB_WEAK) {
1626+ sym->st_value = 0;
1627+ } else {
1628+ tcc_error_noabort("undefined symbol '%s'", name);
1629+ }
1630+ } else if (sh_num < SHN_LORESERVE) {
1631+ /* add section base */
1632+ sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
1633+ }
1634+ found: ;
1635+ }
1636+}
1637+
1638+#ifndef TCC_TARGET_PE
1639+#ifdef TCC_TARGET_X86_64
1640+#define JMP_TABLE_ENTRY_SIZE 14
1641+static uplong add_jmp_table(TCCState *s1, uplong val)
1642+{
1643+ char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
1644+ s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
1645+ /* jmp *0x0(%rip) */
1646+ p[0] = 0xff;
1647+ p[1] = 0x25;
1648+ *(int *)(p + 2) = 0;
1649+ *(uplong *)(p + 6) = val;
1650+ return (uplong)p;
1651+}
1652+
1653+static uplong add_got_table(TCCState *s1, uplong val)
1654+{
1655+ uplong *p = (uplong *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
1656+ s1->runtime_plt_and_got_offset += sizeof(uplong);
1657+ *p = val;
1658+ return (uplong)p;
1659+}
1660+#elif defined TCC_TARGET_ARM
1661+#define JMP_TABLE_ENTRY_SIZE 8
1662+static uplong add_jmp_table(TCCState *s1, int val)
1663+{
1664+ uint32_t *p = (uint32_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
1665+ s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
1666+ /* ldr pc, [pc, #-4] */
1667+ p[0] = 0xE51FF004;
1668+ p[1] = val;
1669+ return (uplong)p;
1670+}
1671+#endif
1672+#endif
1673+
1674+/* relocate a given section (CPU dependent) */
1675+ST_FUNC void relocate_section(TCCState *s1, Section *s)
1676+{
1677+ Section *sr;
1678+ ElfW_Rel *rel, *rel_end, *qrel;
1679+ ElfW(Sym) *sym;
1680+ int type, sym_index;
1681+ unsigned char *ptr;
1682+ uplong val, addr;
1683+#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
1684+ int esym_index;
1685+#endif
1686+
1687+ sr = s->reloc;
1688+ rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
1689+ qrel = (ElfW_Rel *)sr->data;
1690+ for(rel = qrel;
1691+ rel < rel_end;
1692+ rel++) {
1693+ ptr = s->data + rel->r_offset;
1694+
1695+ sym_index = ELFW(R_SYM)(rel->r_info);
1696+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1697+ val = sym->st_value;
1698+#ifdef TCC_TARGET_X86_64
1699+ val += rel->r_addend;
1700+#endif
1701+ type = ELFW(R_TYPE)(rel->r_info);
1702+ addr = s->sh_addr + rel->r_offset;
1703+
1704+ /* CPU specific */
1705+ switch(type) {
1706+#if defined(TCC_TARGET_I386)
1707+ case R_386_32:
1708+ if (s1->output_type == TCC_OUTPUT_DLL) {
1709+ esym_index = s1->symtab_to_dynsym[sym_index];
1710+ qrel->r_offset = rel->r_offset;
1711+ if (esym_index) {
1712+ qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
1713+ qrel++;
1714+ break;
1715+ } else {
1716+ qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
1717+ qrel++;
1718+ }
1719+ }
1720+ *(int *)ptr += val;
1721+ break;
1722+ case R_386_PC32:
1723+ if (s1->output_type == TCC_OUTPUT_DLL) {
1724+ /* DLL relocation */
1725+ esym_index = s1->symtab_to_dynsym[sym_index];
1726+ if (esym_index) {
1727+ qrel->r_offset = rel->r_offset;
1728+ qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
1729+ qrel++;
1730+ break;
1731+ }
1732+ }
1733+ *(int *)ptr += val - addr;
1734+ break;
1735+ case R_386_PLT32:
1736+ *(int *)ptr += val - addr;
1737+ break;
1738+ case R_386_GLOB_DAT:
1739+ case R_386_JMP_SLOT:
1740+ *(int *)ptr = val;
1741+ break;
1742+ case R_386_GOTPC:
1743+ *(int *)ptr += s1->got->sh_addr - addr;
1744+ break;
1745+ case R_386_GOTOFF:
1746+ *(int *)ptr += val - s1->got->sh_addr;
1747+ break;
1748+ case R_386_GOT32:
1749+ /* we load the got offset */
1750+ *(int *)ptr += s1->got_offsets[sym_index];
1751+ break;
1752+ case R_386_16:
1753+ if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
1754+ output_file:
1755+ tcc_error("can only produce 16-bit binary files");
1756+ }
1757+ *(short *)ptr += val;
1758+ break;
1759+ case R_386_PC16:
1760+ if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
1761+ goto output_file;
1762+ *(short *)ptr += val - addr;
1763+ break;
1764+#elif defined(TCC_TARGET_ARM)
1765+ case R_ARM_PC24:
1766+ case R_ARM_CALL:
1767+ case R_ARM_JUMP24:
1768+ case R_ARM_PLT32:
1769+ {
1770+ int x;
1771+ x = (*(int *)ptr)&0xffffff;
1772+ (*(int *)ptr) &= 0xff000000;
1773+ if (x & 0x800000)
1774+ x -= 0x1000000;
1775+ x *= 4;
1776+ x += val - addr;
1777+#ifndef TCC_TARGET_PE
1778+ if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
1779+ if (s1->output_type == TCC_OUTPUT_MEMORY)
1780+ x += add_jmp_table(s1, val) - val; /* add veneer */
1781+#endif
1782+ if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
1783+ tcc_error("can't relocate value at %x",addr);
1784+ x >>= 2;
1785+ x &= 0xffffff;
1786+ (*(int *)ptr) |= x;
1787+ }
1788+ break;
1789+ case R_ARM_PREL31:
1790+ {
1791+ int x;
1792+ x = (*(int *)ptr) & 0x7fffffff;
1793+ (*(int *)ptr) &= 0x80000000;
1794+ x = (x * 2) / 2;
1795+ x += val - addr;
1796+ if((x^(x>>1))&0x40000000)
1797+ tcc_error("can't relocate value at %x",addr);
1798+ (*(int *)ptr) |= x & 0x7fffffff;
1799+ }
1800+ case R_ARM_ABS32:
1801+ *(int *)ptr += val;
1802+ break;
1803+ case R_ARM_REL32:
1804+ *(int *)ptr += val - addr;
1805+ case R_ARM_BASE_PREL:
1806+ *(int *)ptr += s1->got->sh_addr - addr;
1807+ break;
1808+ case R_ARM_GOTOFF32:
1809+ *(int *)ptr += val - s1->got->sh_addr;
1810+ break;
1811+ case R_ARM_GOT_BREL:
1812+ /* we load the got offset */
1813+ *(int *)ptr += s1->got_offsets[sym_index];
1814+ break;
1815+ case R_ARM_COPY:
1816+ break;
1817+ case R_ARM_V4BX:
1818+ /* trade Thumb support for ARMv4 support */
1819+ if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
1820+ *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
1821+ break;
1822+ default:
1823+ fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
1824+ type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
1825+ break;
1826+#elif defined(TCC_TARGET_C67)
1827+ case R_C60_32:
1828+ *(int *)ptr += val;
1829+ break;
1830+ case R_C60LO16:
1831+ {
1832+ uint32_t orig;
1833+
1834+ /* put the low 16 bits of the absolute address */
1835+ // add to what is already there
1836+
1837+ orig = ((*(int *)(ptr )) >> 7) & 0xffff;
1838+ orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
1839+
1840+ //patch both at once - assumes always in pairs Low - High
1841+
1842+ *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
1843+ *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
1844+ }
1845+ break;
1846+ case R_C60HI16:
1847+ break;
1848+ default:
1849+ fprintf(stderr,"FIXME: handle reloc type %x at %x [%.8x] to %x\n",
1850+ type, (unsigned)addr, (unsigned)(uplong)ptr, (unsigned)val);
1851+ break;
1852+#elif defined(TCC_TARGET_X86_64)
1853+ case R_X86_64_64:
1854+ if (s1->output_type == TCC_OUTPUT_DLL) {
1855+ qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
1856+ qrel->r_addend = *(long long *)ptr + val;
1857+ qrel++;
1858+ }
1859+ *(long long *)ptr += val;
1860+ break;
1861+ case R_X86_64_32:
1862+ case R_X86_64_32S:
1863+ if (s1->output_type == TCC_OUTPUT_DLL) {
1864+ /* XXX: this logic may depend on TCC's codegen
1865+ now TCC uses R_X86_64_32 even for a 64bit pointer */
1866+ qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
1867+ qrel->r_addend = *(int *)ptr + val;
1868+ qrel++;
1869+ }
1870+ *(int *)ptr += val;
1871+ break;
1872+
1873+ case R_X86_64_PC32:
1874+ if (s1->output_type == TCC_OUTPUT_DLL) {
1875+ /* DLL relocation */
1876+ esym_index = s1->symtab_to_dynsym[sym_index];
1877+ if (esym_index) {
1878+ qrel->r_offset = rel->r_offset;
1879+ qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
1880+ qrel->r_addend = *(int *)ptr;
1881+ qrel++;
1882+ break;
1883+ }
1884+ }
1885+ /* fall through */
1886+ case R_X86_64_PLT32: {
1887+ long long diff;
1888+ diff = (long long)val - addr;
1889+ if (diff <= -2147483647 || diff > 2147483647) {
1890+#ifndef TCC_TARGET_PE
1891+ /* XXX: naive support for over 32bit jump */
1892+ if (s1->output_type == TCC_OUTPUT_MEMORY) {
1893+ val = (add_jmp_table(s1, val - rel->r_addend) +
1894+ rel->r_addend);
1895+ diff = val - addr;
1896+ }
1897+#endif
1898+ if (diff <= -2147483647 || diff > 2147483647) {
1899+ tcc_error("internal error: relocation failed");
1900+ }
1901+ }
1902+ *(int *)ptr += diff;
1903+ }
1904+ break;
1905+ case R_X86_64_GLOB_DAT:
1906+ case R_X86_64_JUMP_SLOT:
1907+ /* They don't need addend */
1908+ *(int *)ptr = val - rel->r_addend;
1909+ break;
1910+ case R_X86_64_GOTPCREL:
1911+#ifndef TCC_TARGET_PE
1912+ if (s1->output_type == TCC_OUTPUT_MEMORY) {
1913+ val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
1914+ *(int *)ptr += val - addr;
1915+ break;
1916+ }
1917+#endif
1918+ *(int *)ptr += (s1->got->sh_addr - addr +
1919+ s1->got_offsets[sym_index] - 4);
1920+ break;
1921+ case R_X86_64_GOTTPOFF:
1922+ *(int *)ptr += val - s1->got->sh_addr;
1923+ break;
1924+ case R_X86_64_GOT32:
1925+ /* we load the got offset */
1926+ *(int *)ptr += s1->got_offsets[sym_index];
1927+ break;
1928+#else
1929+#error unsupported processor
1930+#endif
1931+ }
1932+ }
1933+ /* if the relocation is allocated, we change its symbol table */
1934+ if (sr->sh_flags & SHF_ALLOC)
1935+ sr->link = s1->dynsym;
1936+}
1937+
1938+/* relocate relocation table in 'sr' */
1939+static void relocate_rel(TCCState *s1, Section *sr)
1940+{
1941+ Section *s;
1942+ ElfW_Rel *rel, *rel_end;
1943+
1944+ s = s1->sections[sr->sh_info];
1945+ rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
1946+ for(rel = (ElfW_Rel *)sr->data;
1947+ rel < rel_end;
1948+ rel++) {
1949+ rel->r_offset += s->sh_addr;
1950+ }
1951+}
1952+
1953+/* count the number of dynamic relocations so that we can reserve
1954+ their space */
1955+static int prepare_dynamic_rel(TCCState *s1, Section *sr)
1956+{
1957+ ElfW_Rel *rel, *rel_end;
1958+ int sym_index, esym_index, type, count;
1959+
1960+ count = 0;
1961+ rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
1962+ for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
1963+ sym_index = ELFW(R_SYM)(rel->r_info);
1964+ type = ELFW(R_TYPE)(rel->r_info);
1965+ switch(type) {
1966+#if defined(TCC_TARGET_I386)
1967+ case R_386_32:
1968+#elif defined(TCC_TARGET_X86_64)
1969+ case R_X86_64_32:
1970+ case R_X86_64_32S:
1971+ case R_X86_64_64:
1972+#endif
1973+ count++;
1974+ break;
1975+#if defined(TCC_TARGET_I386)
1976+ case R_386_PC32:
1977+#elif defined(TCC_TARGET_X86_64)
1978+ case R_X86_64_PC32:
1979+#endif
1980+ esym_index = s1->symtab_to_dynsym[sym_index];
1981+ if (esym_index)
1982+ count++;
1983+ break;
1984+ default:
1985+ break;
1986+ }
1987+ }
1988+ if (count) {
1989+ /* allocate the section */
1990+ sr->sh_flags |= SHF_ALLOC;
1991+ sr->sh_size = count * sizeof(ElfW_Rel);
1992+ }
1993+ return count;
1994+}
1995+
1996+static void put_got_offset(TCCState *s1, int index, unsigned long val)
1997+{
1998+ int n;
1999+ unsigned long *tab;
2000+
2001+ if (index >= s1->nb_got_offsets) {
2002+ /* find immediately bigger power of 2 and reallocate array */
2003+ n = 1;
2004+ while (index >= n)
2005+ n *= 2;
2006+ tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
2007+ s1->got_offsets = tab;
2008+ memset(s1->got_offsets + s1->nb_got_offsets, 0,
2009+ (n - s1->nb_got_offsets) * sizeof(unsigned long));
2010+ s1->nb_got_offsets = n;
2011+ }
2012+ s1->got_offsets[index] = val;
2013+}
2014+
2015+/* XXX: suppress that */
2016+static void put32(unsigned char *p, uint32_t val)
2017+{
2018+ p[0] = val;
2019+ p[1] = val >> 8;
2020+ p[2] = val >> 16;
2021+ p[3] = val >> 24;
2022+}
2023+
2024+#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
2025+ defined(TCC_TARGET_X86_64)
2026+static uint32_t get32(unsigned char *p)
2027+{
2028+ return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
2029+}
2030+#endif
2031+
2032+static void build_got(TCCState *s1)
2033+{
2034+ unsigned char *ptr;
2035+
2036+ /* if no got, then create it */
2037+ s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
2038+ s1->got->sh_entsize = 4;
2039+ add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
2040+ 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
2041+ ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
2042+#if PTR_SIZE == 4
2043+ /* keep space for _DYNAMIC pointer, if present */
2044+ put32(ptr, 0);
2045+ /* two dummy got entries */
2046+ put32(ptr + 4, 0);
2047+ put32(ptr + 8, 0);
2048+#else
2049+ /* keep space for _DYNAMIC pointer, if present */
2050+ put32(ptr, 0);
2051+ put32(ptr + 4, 0);
2052+ /* two dummy got entries */
2053+ put32(ptr + 8, 0);
2054+ put32(ptr + 12, 0);
2055+ put32(ptr + 16, 0);
2056+ put32(ptr + 20, 0);
2057+#endif
2058+}
2059+
2060+/* put a got entry corresponding to a symbol in symtab_section. 'size'
2061+ and 'info' can be modifed if more precise info comes from the DLL */
2062+static void put_got_entry(TCCState *s1,
2063+ int reloc_type, unsigned long size, int info,
2064+ int sym_index)
2065+{
2066+ int index;
2067+ const char *name;
2068+ ElfW(Sym) *sym;
2069+ unsigned long offset;
2070+ int *ptr;
2071+
2072+ if (!s1->got)
2073+ build_got(s1);
2074+
2075+ /* if a got entry already exists for that symbol, no need to add one */
2076+ if (sym_index < s1->nb_got_offsets &&
2077+ s1->got_offsets[sym_index] != 0)
2078+ return;
2079+
2080+ put_got_offset(s1, sym_index, s1->got->data_offset);
2081+
2082+ if (s1->dynsym) {
2083+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2084+ name = symtab_section->link->data + sym->st_name;
2085+ offset = sym->st_value;
2086+#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
2087+ if (reloc_type ==
2088+#ifdef TCC_TARGET_X86_64
2089+ R_X86_64_JUMP_SLOT
2090+#else
2091+ R_386_JMP_SLOT
2092+#endif
2093+ ) {
2094+ Section *plt;
2095+ uint8_t *p;
2096+ int modrm;
2097+
2098+#if defined(TCC_OUTPUT_DLL_WITH_PLT)
2099+ modrm = 0x25;
2100+#else
2101+ /* if we build a DLL, we add a %ebx offset */
2102+ if (s1->output_type == TCC_OUTPUT_DLL)
2103+ modrm = 0xa3;
2104+ else
2105+ modrm = 0x25;
2106+#endif
2107+
2108+ /* add a PLT entry */
2109+ plt = s1->plt;
2110+ if (plt->data_offset == 0) {
2111+ /* first plt entry */
2112+ p = section_ptr_add(plt, 16);
2113+ p[0] = 0xff; /* pushl got + PTR_SIZE */
2114+ p[1] = modrm + 0x10;
2115+ put32(p + 2, PTR_SIZE);
2116+ p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
2117+ p[7] = modrm;
2118+ put32(p + 8, PTR_SIZE * 2);
2119+ }
2120+
2121+ p = section_ptr_add(plt, 16);
2122+ p[0] = 0xff; /* jmp *(got + x) */
2123+ p[1] = modrm;
2124+ put32(p + 2, s1->got->data_offset);
2125+ p[6] = 0x68; /* push $xxx */
2126+ put32(p + 7, (plt->data_offset - 32) >> 1);
2127+ p[11] = 0xe9; /* jmp plt_start */
2128+ put32(p + 12, -(plt->data_offset));
2129+
2130+ /* the symbol is modified so that it will be relocated to
2131+ the PLT */
2132+#if !defined(TCC_OUTPUT_DLL_WITH_PLT)
2133+ if (s1->output_type == TCC_OUTPUT_EXE)
2134+#endif
2135+ offset = plt->data_offset - 16;
2136+ }
2137+#elif defined(TCC_TARGET_ARM)
2138+ if (reloc_type == R_ARM_JUMP_SLOT) {
2139+ Section *plt;
2140+ uint8_t *p;
2141+
2142+ /* if we build a DLL, we add a %ebx offset */
2143+ if (s1->output_type == TCC_OUTPUT_DLL)
2144+ tcc_error("DLLs unimplemented!");
2145+
2146+ /* add a PLT entry */
2147+ plt = s1->plt;
2148+ if (plt->data_offset == 0) {
2149+ /* first plt entry */
2150+ p = section_ptr_add(plt, 16);
2151+ put32(p , 0xe52de004);
2152+ put32(p + 4, 0xe59fe010);
2153+ put32(p + 8, 0xe08fe00e);
2154+ put32(p + 12, 0xe5bef008);
2155+ }
2156+
2157+ p = section_ptr_add(plt, 16);
2158+ put32(p , 0xe59fc004);
2159+ put32(p+4, 0xe08fc00c);
2160+ put32(p+8, 0xe59cf000);
2161+ put32(p+12, s1->got->data_offset);
2162+
2163+ /* the symbol is modified so that it will be relocated to
2164+ the PLT */
2165+ if (s1->output_type == TCC_OUTPUT_EXE)
2166+ offset = plt->data_offset - 16;
2167+ }
2168+#elif defined(TCC_TARGET_C67)
2169+ tcc_error("C67 got not implemented");
2170+#else
2171+#error unsupported CPU
2172+#endif
2173+ index = put_elf_sym(s1->dynsym, offset,
2174+ size, info, 0, sym->st_shndx, name);
2175+ /* put a got entry */
2176+ put_elf_reloc(s1->dynsym, s1->got,
2177+ s1->got->data_offset,
2178+ reloc_type, index);
2179+ }
2180+ ptr = section_ptr_add(s1->got, PTR_SIZE);
2181+ *ptr = 0;
2182+}
2183+
2184+/* build GOT and PLT entries */
2185+ST_FUNC void build_got_entries(TCCState *s1)
2186+{
2187+ Section *s;
2188+ ElfW_Rel *rel, *rel_end;
2189+ ElfW(Sym) *sym;
2190+ int i, type, reloc_type, sym_index;
2191+
2192+ for(i = 1; i < s1->nb_sections; i++) {
2193+ s = s1->sections[i];
2194+ if (s->sh_type != SHT_RELX)
2195+ continue;
2196+ /* no need to handle got relocations */
2197+ if (s->link != symtab_section)
2198+ continue;
2199+ rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2200+ for(rel = (ElfW_Rel *)s->data;
2201+ rel < rel_end;
2202+ rel++) {
2203+ type = ELFW(R_TYPE)(rel->r_info);
2204+ switch(type) {
2205+#if defined(TCC_TARGET_I386)
2206+ case R_386_GOT32:
2207+ case R_386_GOTOFF:
2208+ case R_386_GOTPC:
2209+ case R_386_PLT32:
2210+ if (!s1->got)
2211+ build_got(s1);
2212+ if (type == R_386_GOT32 || type == R_386_PLT32) {
2213+ sym_index = ELFW(R_SYM)(rel->r_info);
2214+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2215+ /* look at the symbol got offset. If none, then add one */
2216+ if (type == R_386_GOT32)
2217+ reloc_type = R_386_GLOB_DAT;
2218+ else
2219+ reloc_type = R_386_JMP_SLOT;
2220+ put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
2221+ sym_index);
2222+ }
2223+ break;
2224+#elif defined(TCC_TARGET_ARM)
2225+ case R_ARM_GOT_BREL:
2226+ case R_ARM_GOTOFF32:
2227+ case R_ARM_BASE_PREL:
2228+ case R_ARM_PLT32:
2229+ if (!s1->got)
2230+ build_got(s1);
2231+ if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
2232+ sym_index = ELFW(R_SYM)(rel->r_info);
2233+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2234+ /* look at the symbol got offset. If none, then add one */
2235+ if (type == R_ARM_GOT_BREL)
2236+ reloc_type = R_ARM_GLOB_DAT;
2237+ else
2238+ reloc_type = R_ARM_JUMP_SLOT;
2239+ put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
2240+ sym_index);
2241+ }
2242+ break;
2243+#elif defined(TCC_TARGET_C67)
2244+ case R_C60_GOT32:
2245+ case R_C60_GOTOFF:
2246+ case R_C60_GOTPC:
2247+ case R_C60_PLT32:
2248+ if (!s1->got)
2249+ build_got(s1);
2250+ if (type == R_C60_GOT32 || type == R_C60_PLT32) {
2251+ sym_index = ELFW(R_SYM)(rel->r_info);
2252+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2253+ /* look at the symbol got offset. If none, then add one */
2254+ if (type == R_C60_GOT32)
2255+ reloc_type = R_C60_GLOB_DAT;
2256+ else
2257+ reloc_type = R_C60_JMP_SLOT;
2258+ put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
2259+ sym_index);
2260+ }
2261+ break;
2262+#elif defined(TCC_TARGET_X86_64)
2263+ case R_X86_64_GOT32:
2264+ case R_X86_64_GOTTPOFF:
2265+ case R_X86_64_GOTPCREL:
2266+ case R_X86_64_PLT32:
2267+ if (!s1->got)
2268+ build_got(s1);
2269+ if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
2270+ type == R_X86_64_PLT32) {
2271+ sym_index = ELFW(R_SYM)(rel->r_info);
2272+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2273+ /* look at the symbol got offset. If none, then add one */
2274+ if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
2275+ reloc_type = R_X86_64_GLOB_DAT;
2276+ else
2277+ reloc_type = R_X86_64_JUMP_SLOT;
2278+ put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
2279+ sym_index);
2280+ }
2281+ break;
2282+#else
2283+#error unsupported CPU
2284+#endif
2285+ default:
2286+ break;
2287+ }
2288+ }
2289+ }
2290+}
2291+
2292+ST_FUNC Section *new_symtab(TCCState *s1,
2293+ const char *symtab_name, int sh_type, int sh_flags,
2294+ const char *strtab_name,
2295+ const char *hash_name, int hash_sh_flags)
2296+{
2297+ Section *symtab, *strtab, *hash;
2298+ int *ptr, nb_buckets;
2299+
2300+ symtab = new_section(s1, symtab_name, sh_type, sh_flags);
2301+ symtab->sh_entsize = sizeof(ElfW(Sym));
2302+ strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
2303+ put_elf_str(strtab, "");
2304+ symtab->link = strtab;
2305+ put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
2306+
2307+ nb_buckets = 1;
2308+
2309+ hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
2310+ hash->sh_entsize = sizeof(int);
2311+ symtab->hash = hash;
2312+ hash->link = symtab;
2313+
2314+ ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
2315+ ptr[0] = nb_buckets;
2316+ ptr[1] = 1;
2317+ memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
2318+ return symtab;
2319+}
2320+
2321+/* put dynamic tag */
2322+static void put_dt(Section *dynamic, int dt, uplong val)
2323+{
2324+ ElfW(Dyn) *dyn;
2325+ dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
2326+ dyn->d_tag = dt;
2327+ dyn->d_un.d_val = val;
2328+}
2329+
2330+static void add_init_array_defines(TCCState *s1, const char *section_name)
2331+{
2332+ Section *s;
2333+ long end_offset;
2334+ char sym_start[1024];
2335+ char sym_end[1024];
2336+
2337+ snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
2338+ snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
2339+
2340+ s = find_section(s1, section_name);
2341+ if (!s) {
2342+ end_offset = 0;
2343+ s = data_section;
2344+ } else {
2345+ end_offset = s->data_offset;
2346+ }
2347+
2348+ add_elf_sym(symtab_section,
2349+ 0, 0,
2350+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
2351+ s->sh_num, sym_start);
2352+ add_elf_sym(symtab_section,
2353+ end_offset, 0,
2354+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
2355+ s->sh_num, sym_end);
2356+}
2357+
2358+static int tcc_add_support(TCCState *s1, const char *filename)
2359+{
2360+ char buf[1024];
2361+ snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
2362+ return tcc_add_file(s1, buf);
2363+}
2364+
2365+ST_FUNC void tcc_add_bcheck(TCCState *s1)
2366+{
2367+#ifdef CONFIG_TCC_BCHECK
2368+ unsigned long *ptr;
2369+ Section *init_section;
2370+ unsigned char *pinit;
2371+ int sym_index;
2372+
2373+ if (0 == s1->do_bounds_check)
2374+ return;
2375+
2376+ /* XXX: add an object file to do that */
2377+ ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
2378+ *ptr = 0;
2379+ add_elf_sym(symtab_section, 0, 0,
2380+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
2381+ bounds_section->sh_num, "__bounds_start");
2382+ /* add bound check code */
2383+#ifndef TCC_TARGET_PE
2384+ tcc_add_support(s1, "bcheck.o");
2385+#endif
2386+#ifdef TCC_TARGET_I386
2387+ if (s1->output_type != TCC_OUTPUT_MEMORY) {
2388+ /* add 'call __bound_init()' in .init section */
2389+ init_section = find_section(s1, ".init");
2390+ pinit = section_ptr_add(init_section, 5);
2391+ pinit[0] = 0xe8;
2392+ put32(pinit + 1, -4);
2393+ sym_index = find_elf_sym(symtab_section, "__bound_init");
2394+ put_elf_reloc(symtab_section, init_section,
2395+ init_section->data_offset - 4, R_386_PC32, sym_index);
2396+ }
2397+#endif
2398+#endif
2399+}
2400+
2401+/* add tcc runtime libraries */
2402+ST_FUNC void tcc_add_runtime(TCCState *s1)
2403+{
2404+ tcc_add_bcheck(s1);
2405+
2406+ /* add libc */
2407+ if (!s1->nostdlib) {
2408+ tcc_add_library(s1, "c");
2409+#ifdef CONFIG_USE_LIBGCC
2410+ tcc_add_file(s1, TCC_LIBGCC);
2411+#elif !defined WITHOUT_LIBTCC
2412+ tcc_add_support(s1, "libtcc1.a");
2413+#endif
2414+ /* add crt end if not memory output */
2415+ if (s1->output_type != TCC_OUTPUT_MEMORY)
2416+ tcc_add_crt(s1, "crtn.o");
2417+ }
2418+}
2419+
2420+/* add various standard linker symbols (must be done after the
2421+ sections are filled (for example after allocating common
2422+ symbols)) */
2423+ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
2424+{
2425+ char buf[1024];
2426+ int i;
2427+ Section *s;
2428+
2429+ add_elf_sym(symtab_section,
2430+ text_section->data_offset, 0,
2431+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
2432+ text_section->sh_num, "_etext");
2433+ add_elf_sym(symtab_section,
2434+ data_section->data_offset, 0,
2435+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
2436+ data_section->sh_num, "_edata");
2437+ add_elf_sym(symtab_section,
2438+ bss_section->data_offset, 0,
2439+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
2440+ bss_section->sh_num, "_end");
2441+ /* horrible new standard ldscript defines */
2442+ add_init_array_defines(s1, ".preinit_array");
2443+ add_init_array_defines(s1, ".init_array");
2444+ add_init_array_defines(s1, ".fini_array");
2445+
2446+ /* add start and stop symbols for sections whose name can be
2447+ expressed in C */
2448+ for(i = 1; i < s1->nb_sections; i++) {
2449+ s = s1->sections[i];
2450+ if (s->sh_type == SHT_PROGBITS &&
2451+ (s->sh_flags & SHF_ALLOC)) {
2452+ const char *p;
2453+ int ch;
2454+
2455+ /* check if section name can be expressed in C */
2456+ p = s->name;
2457+ for(;;) {
2458+ ch = *p;
2459+ if (!ch)
2460+ break;
2461+ if (!isid(ch) && !isnum(ch))
2462+ goto next_sec;
2463+ p++;
2464+ }
2465+ snprintf(buf, sizeof(buf), "__start_%s", s->name);
2466+ add_elf_sym(symtab_section,
2467+ 0, 0,
2468+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
2469+ s->sh_num, buf);
2470+ snprintf(buf, sizeof(buf), "__stop_%s", s->name);
2471+ add_elf_sym(symtab_section,
2472+ s->data_offset, 0,
2473+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
2474+ s->sh_num, buf);
2475+ }
2476+ next_sec: ;
2477+ }
2478+}
2479+
2480+static void tcc_output_binary(TCCState *s1, FILE *f,
2481+ const int *section_order)
2482+{
2483+ Section *s;
2484+ int i, offset, size;
2485+
2486+ offset = 0;
2487+ for(i=1;i<s1->nb_sections;i++) {
2488+ s = s1->sections[section_order[i]];
2489+ if (s->sh_type != SHT_NOBITS &&
2490+ (s->sh_flags & SHF_ALLOC)) {
2491+ while (offset < s->sh_offset) {
2492+ fputc(0, f);
2493+ offset++;
2494+ }
2495+ size = s->sh_size;
2496+ fwrite(s->data, 1, size, f);
2497+ offset += size;
2498+ }
2499+ }
2500+}
2501+
2502+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2503+#define HAVE_PHDR 1
2504+#define EXTRA_RELITEMS 14
2505+
2506+/* move the relocation value from .dynsym to .got */
2507+void patch_dynsym_undef(TCCState *s1, Section *s)
2508+{
2509+ uint32_t *gotd = (void *)s1->got->data;
2510+ ElfW(Sym) *sym, *sym_end;
2511+
2512+ gotd += 3; // dummy entries in .got
2513+ /* relocate symbols in .dynsym */
2514+ sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
2515+ for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
2516+ if (sym->st_shndx == SHN_UNDEF) {
2517+ *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
2518+ sym->st_value = 0;
2519+ }
2520+ }
2521+}
2522+#else
2523+#define HAVE_PHDR 0
2524+#define EXTRA_RELITEMS 9
2525+
2526+/* zero plt offsets of weak symbols in .dynsym */
2527+void patch_dynsym_undef(TCCState *s1, Section *s)
2528+{
2529+ ElfW(Sym) *sym, *sym_end;
2530+
2531+ sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
2532+ for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
2533+ if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
2534+ sym->st_value = 0;
2535+}
2536+#endif
2537+
2538+ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
2539+{
2540+ int sym_index = ELFW(R_SYM) (rel->r_info);
2541+ ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
2542+ unsigned long offset;
2543+
2544+ if (sym_index >= s1->nb_got_offsets)
2545+ return;
2546+ offset = s1->got_offsets[sym_index];
2547+ section_reserve(s1->got, offset + PTR_SIZE);
2548+#ifdef TCC_TARGET_X86_64
2549+ /* only works for x86-64 */
2550+ put32(s1->got->data + offset + 4, sym->st_value >> 32);
2551+#endif
2552+ put32(s1->got->data + offset, sym->st_value & 0xffffffff);
2553+}
2554+
2555+ST_FUNC void fill_got(TCCState *s1)
2556+{
2557+ Section *s;
2558+ ElfW_Rel *rel, *rel_end;
2559+ int i;
2560+
2561+ for(i = 1; i < s1->nb_sections; i++) {
2562+ s = s1->sections[i];
2563+ if (s->sh_type != SHT_RELX)
2564+ continue;
2565+ /* no need to handle got relocations */
2566+ if (s->link != symtab_section)
2567+ continue;
2568+ rel_end = (ElfW_Rel *) (s->data + s->data_offset);
2569+ for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
2570+ switch (ELFW(R_TYPE) (rel->r_info)) {
2571+ case R_X86_64_GOT32:
2572+ case R_X86_64_GOTPCREL:
2573+ case R_X86_64_PLT32:
2574+ fill_got_entry(s1, rel);
2575+ break;
2576+ }
2577+ }
2578+ }
2579+}
2580+
2581+
2582+/* output an ELF file */
2583+/* XXX: suppress unneeded sections */
2584+static int elf_output_file(TCCState *s1, const char *filename)
2585+{
2586+ ElfW(Ehdr) ehdr;
2587+ FILE *f;
2588+ int fd, mode, ret;
2589+ int *section_order;
2590+ int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
2591+ long long tmp;
2592+ uplong addr;
2593+ Section *strsec, *s;
2594+ ElfW(Shdr) shdr, *sh;
2595+ ElfW(Phdr) *phdr, *ph;
2596+ Section *interp, *dynamic, *dynstr;
2597+ unsigned long saved_dynamic_data_offset;
2598+ ElfW(Sym) *sym;
2599+ int type, file_type;
2600+ uplong rel_addr, rel_size;
2601+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2602+ uplong bss_addr, bss_size;
2603+#endif
2604+
2605+ file_type = s1->output_type;
2606+ s1->nb_errors = 0;
2607+
2608+ if (file_type != TCC_OUTPUT_OBJ) {
2609+ tcc_add_runtime(s1);
2610+ }
2611+
2612+ phdr = NULL;
2613+ section_order = NULL;
2614+ interp = NULL;
2615+ dynamic = NULL;
2616+ dynstr = NULL; /* avoid warning */
2617+ saved_dynamic_data_offset = 0; /* avoid warning */
2618+
2619+ if (file_type != TCC_OUTPUT_OBJ) {
2620+ relocate_common_syms();
2621+
2622+ tcc_add_linker_symbols(s1);
2623+
2624+ if (!s1->static_link) {
2625+ const char *name;
2626+ int sym_index, index;
2627+ ElfW(Sym) *esym, *sym_end;
2628+
2629+ if (file_type == TCC_OUTPUT_EXE) {
2630+ char *ptr;
2631+ /* allow override the dynamic loader */
2632+ const char *elfint = getenv("LD_SO");
2633+ if (elfint == NULL)
2634+ elfint = CONFIG_TCC_ELFINTERP;
2635+ /* add interpreter section only if executable */
2636+ interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
2637+ interp->sh_addralign = 1;
2638+ ptr = section_ptr_add(interp, 1+strlen(elfint));
2639+ strcpy(ptr, elfint);
2640+ }
2641+
2642+ /* add dynamic symbol table */
2643+ s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
2644+ ".dynstr",
2645+ ".hash", SHF_ALLOC);
2646+ dynstr = s1->dynsym->link;
2647+
2648+ /* add dynamic section */
2649+ dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
2650+ SHF_ALLOC | SHF_WRITE);
2651+ dynamic->link = dynstr;
2652+ dynamic->sh_entsize = sizeof(ElfW(Dyn));
2653+
2654+ /* add PLT */
2655+ s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
2656+ SHF_ALLOC | SHF_EXECINSTR);
2657+ s1->plt->sh_entsize = 4;
2658+
2659+ build_got(s1);
2660+
2661+ /* scan for undefined symbols and see if they are in the
2662+ dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
2663+ is found, then we add it in the PLT. If a symbol
2664+ STT_OBJECT is found, we add it in the .bss section with
2665+ a suitable relocation */
2666+ sym_end = (ElfW(Sym) *)(symtab_section->data +
2667+ symtab_section->data_offset);
2668+ if (file_type == TCC_OUTPUT_EXE) {
2669+ for(sym = (ElfW(Sym) *)symtab_section->data + 1;
2670+ sym < sym_end;
2671+ sym++) {
2672+ if (sym->st_shndx == SHN_UNDEF) {
2673+ name = symtab_section->link->data + sym->st_name;
2674+ sym_index = find_elf_sym(s1->dynsymtab_section, name);
2675+ if (sym_index) {
2676+ esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
2677+ type = ELFW(ST_TYPE)(esym->st_info);
2678+ if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
2679+ put_got_entry(s1, R_JMP_SLOT, esym->st_size,
2680+ ELFW(ST_INFO)(STB_GLOBAL,type),
2681+ sym - (ElfW(Sym) *)symtab_section->data);
2682+ } else if (type == STT_OBJECT) {
2683+ unsigned long offset;
2684+ ElfW(Sym) *dynsym, *dynsym_end;
2685+ offset = bss_section->data_offset;
2686+ /* XXX: which alignment ? */
2687+ offset = (offset + 16 - 1) & -16;
2688+ index = put_elf_sym(s1->dynsym, offset, esym->st_size,
2689+ esym->st_info, 0,
2690+ bss_section->sh_num, name);
2691+ // Ensure R_COPY works for weak symbol aliases
2692+ if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
2693+ dynsym_end = (ElfW(Sym) *)
2694+ (s1->dynsymtab_section->data +
2695+ s1->dynsymtab_section->data_offset);
2696+ for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
2697+ dynsym < dynsym_end; dynsym++) {
2698+ if ((dynsym->st_value == esym->st_value)
2699+ && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
2700+ char *dynname;
2701+ dynname = s1->dynsymtab_section->link->data
2702+ + dynsym->st_name;
2703+ put_elf_sym(s1->dynsym, offset,
2704+ dynsym->st_size,
2705+ dynsym->st_info, 0,
2706+ bss_section->sh_num,
2707+ dynname);
2708+ break;
2709+ }
2710+ }
2711+ }
2712+ put_elf_reloc(s1->dynsym, bss_section,
2713+ offset, R_COPY, index);
2714+ offset += esym->st_size;
2715+ bss_section->data_offset = offset;
2716+ }
2717+ } else {
2718+ /* STB_WEAK undefined symbols are accepted */
2719+ /* XXX: _fp_hw seems to be part of the ABI, so we ignore
2720+ it */
2721+ if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
2722+ !strcmp(name, "_fp_hw")) {
2723+ } else {
2724+ tcc_error_noabort("undefined symbol '%s'", name);
2725+ }
2726+ }
2727+ } else if (s1->rdynamic &&
2728+ ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2729+ /* if -rdynamic option, then export all non
2730+ local symbols */
2731+ name = symtab_section->link->data + sym->st_name;
2732+ put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
2733+ sym->st_info, 0,
2734+ sym->st_shndx, name);
2735+ }
2736+ }
2737+
2738+ if (s1->nb_errors)
2739+ goto fail;
2740+
2741+ /* now look at unresolved dynamic symbols and export
2742+ corresponding symbol */
2743+ sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
2744+ s1->dynsymtab_section->data_offset);
2745+ for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
2746+ esym < sym_end;
2747+ esym++) {
2748+ if (esym->st_shndx == SHN_UNDEF) {
2749+ name = s1->dynsymtab_section->link->data + esym->st_name;
2750+ sym_index = find_elf_sym(symtab_section, name);
2751+ if (sym_index) {
2752+ /* XXX: avoid adding a symbol if already
2753+ present because of -rdynamic ? */
2754+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2755+ put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
2756+ sym->st_info, 0,
2757+ sym->st_shndx, name);
2758+ } else {
2759+ if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
2760+ /* weak symbols can stay undefined */
2761+ } else {
2762+ tcc_warning("undefined dynamic symbol '%s'", name);
2763+ }
2764+ }
2765+ }
2766+ }
2767+ } else {
2768+ int nb_syms;
2769+ /* shared library case : we simply export all the global symbols */
2770+ nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
2771+ s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
2772+ for(sym = (ElfW(Sym) *)symtab_section->data + 1;
2773+ sym < sym_end;
2774+ sym++) {
2775+ if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2776+#if defined(TCC_OUTPUT_DLL_WITH_PLT)
2777+ if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
2778+ ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
2779+ && sym->st_shndx == SHN_UNDEF) {
2780+ put_got_entry(s1, R_JMP_SLOT, sym->st_size,
2781+ sym->st_info,
2782+ sym - (ElfW(Sym) *)symtab_section->data);
2783+ }
2784+ else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
2785+ put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
2786+ sym->st_info,
2787+ sym - (ElfW(Sym) *)symtab_section->data);
2788+ }
2789+ else
2790+#endif
2791+ {
2792+ name = symtab_section->link->data + sym->st_name;
2793+ index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
2794+ sym->st_info, 0,
2795+ sym->st_shndx, name);
2796+ s1->symtab_to_dynsym[sym -
2797+ (ElfW(Sym) *)symtab_section->data] =
2798+ index;
2799+ }
2800+ }
2801+ }
2802+ }
2803+
2804+ build_got_entries(s1);
2805+
2806+ /* add a list of needed dlls */
2807+ for(i = 0; i < s1->nb_loaded_dlls; i++) {
2808+ DLLReference *dllref = s1->loaded_dlls[i];
2809+ if (dllref->level == 0)
2810+ put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
2811+ }
2812+
2813+ if (s1->rpath)
2814+ put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
2815+
2816+ /* XXX: currently, since we do not handle PIC code, we
2817+ must relocate the readonly segments */
2818+ if (file_type == TCC_OUTPUT_DLL) {
2819+ if (s1->soname)
2820+ put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
2821+ put_dt(dynamic, DT_TEXTREL, 0);
2822+ }
2823+
2824+ if (s1->symbolic)
2825+ put_dt(dynamic, DT_SYMBOLIC, 0);
2826+
2827+ /* add necessary space for other entries */
2828+ saved_dynamic_data_offset = dynamic->data_offset;
2829+ dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
2830+ } else {
2831+ /* still need to build got entries in case of static link */
2832+ build_got_entries(s1);
2833+ }
2834+ }
2835+
2836+ memset(&ehdr, 0, sizeof(ehdr));
2837+
2838+ /* we add a section for symbols */
2839+ strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
2840+ put_elf_str(strsec, "");
2841+
2842+ /* compute number of sections */
2843+ shnum = s1->nb_sections;
2844+
2845+ /* this array is used to reorder sections in the output file */
2846+ section_order = tcc_malloc(sizeof(int) * shnum);
2847+ section_order[0] = 0;
2848+ sh_order_index = 1;
2849+
2850+ /* compute number of program headers */
2851+ switch(file_type) {
2852+ default:
2853+ case TCC_OUTPUT_OBJ:
2854+ phnum = 0;
2855+ break;
2856+ case TCC_OUTPUT_EXE:
2857+ if (!s1->static_link)
2858+ phnum = 4 + HAVE_PHDR;
2859+ else
2860+ phnum = 2;
2861+ break;
2862+ case TCC_OUTPUT_DLL:
2863+ phnum = 3;
2864+ break;
2865+ }
2866+
2867+ /* allocate strings for section names and decide if an unallocated
2868+ section should be output */
2869+ /* NOTE: the strsec section comes last, so its size is also
2870+ correct ! */
2871+ for(i = 1; i < s1->nb_sections; i++) {
2872+ s = s1->sections[i];
2873+ s->sh_name = put_elf_str(strsec, s->name);
2874+#if 0 //gr
2875+ printf("section: f=%08x t=%08x i=%08x %s %s\n",
2876+ s->sh_flags,
2877+ s->sh_type,
2878+ s->sh_info,
2879+ s->name,
2880+ s->reloc ? s->reloc->name : "n"
2881+ );
2882+#endif
2883+ /* when generating a DLL, we include relocations but we may
2884+ patch them */
2885+ if (file_type == TCC_OUTPUT_DLL &&
2886+ s->sh_type == SHT_RELX &&
2887+ !(s->sh_flags & SHF_ALLOC)) {
2888+ /* //gr: avoid bogus relocs for empty (debug) sections */
2889+ if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
2890+ prepare_dynamic_rel(s1, s);
2891+ else if (s1->do_debug)
2892+ s->sh_size = s->data_offset;
2893+ } else if (s1->do_debug ||
2894+ file_type == TCC_OUTPUT_OBJ ||
2895+ (s->sh_flags & SHF_ALLOC) ||
2896+ i == (s1->nb_sections - 1)) {
2897+ /* we output all sections if debug or object file */
2898+ s->sh_size = s->data_offset;
2899+ }
2900+ }
2901+
2902+ /* allocate program segment headers */
2903+ phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
2904+
2905+ if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2906+ file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2907+ } else {
2908+ file_offset = 0;
2909+ }
2910+ if (phnum > 0) {
2911+ /* compute section to program header mapping */
2912+ if (s1->has_text_addr) {
2913+ int a_offset, p_offset;
2914+ addr = s1->text_addr;
2915+ /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
2916+ ELF_PAGE_SIZE */
2917+ a_offset = (int) (addr & (s1->section_align - 1));
2918+ p_offset = file_offset & (s1->section_align - 1);
2919+ if (a_offset < p_offset)
2920+ a_offset += s1->section_align;
2921+ file_offset += (a_offset - p_offset);
2922+ } else {
2923+ if (file_type == TCC_OUTPUT_DLL)
2924+ addr = 0;
2925+ else
2926+ addr = ELF_START_ADDR;
2927+ /* compute address after headers */
2928+ addr += (file_offset & (s1->section_align - 1));
2929+ }
2930+
2931+ /* dynamic relocation table information, for .dynamic section */
2932+ rel_size = 0;
2933+ rel_addr = 0;
2934+
2935+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2936+ bss_addr = bss_size = 0;
2937+#endif
2938+ /* leave one program header for the program interpreter */
2939+ ph = &phdr[0];
2940+ if (interp)
2941+ ph += 1 + HAVE_PHDR;
2942+
2943+ for(j = 0; j < 2; j++) {
2944+ ph->p_type = PT_LOAD;
2945+ if (j == 0)
2946+ ph->p_flags = PF_R | PF_X;
2947+ else
2948+ ph->p_flags = PF_R | PF_W;
2949+ ph->p_align = s1->section_align;
2950+
2951+ /* we do the following ordering: interp, symbol tables,
2952+ relocations, progbits, nobits */
2953+ /* XXX: do faster and simpler sorting */
2954+ for(k = 0; k < 5; k++) {
2955+ for(i = 1; i < s1->nb_sections; i++) {
2956+ s = s1->sections[i];
2957+ /* compute if section should be included */
2958+ if (j == 0) {
2959+ if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
2960+ SHF_ALLOC)
2961+ continue;
2962+ } else {
2963+ if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
2964+ (SHF_ALLOC | SHF_WRITE))
2965+ continue;
2966+ }
2967+ if (s == interp) {
2968+ if (k != 0)
2969+ continue;
2970+ } else if (s->sh_type == SHT_DYNSYM ||
2971+ s->sh_type == SHT_STRTAB ||
2972+ s->sh_type == SHT_HASH) {
2973+ if (k != 1)
2974+ continue;
2975+ } else if (s->sh_type == SHT_RELX) {
2976+ if (k != 2)
2977+ continue;
2978+ } else if (s->sh_type == SHT_NOBITS) {
2979+ if (k != 4)
2980+ continue;
2981+ } else {
2982+ if (k != 3)
2983+ continue;
2984+ }
2985+ section_order[sh_order_index++] = i;
2986+
2987+ /* section matches: we align it and add its size */
2988+ tmp = addr;
2989+ addr = (addr + s->sh_addralign - 1) &
2990+ ~(s->sh_addralign - 1);
2991+ file_offset += (int) ( addr - tmp );
2992+ s->sh_offset = file_offset;
2993+ s->sh_addr = addr;
2994+
2995+ /* update program header infos */
2996+ if (ph->p_offset == 0) {
2997+ ph->p_offset = file_offset;
2998+ ph->p_vaddr = addr;
2999+ ph->p_paddr = ph->p_vaddr;
3000+ }
3001+ /* update dynamic relocation infos */
3002+ if (s->sh_type == SHT_RELX) {
3003+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
3004+ if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
3005+ rel_addr = addr;
3006+ rel_size += s->sh_size; // XXX only first rel.
3007+ }
3008+ if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
3009+ bss_addr = addr;
3010+ bss_size = s->sh_size; // XXX only first rel.
3011+ }
3012+#else
3013+ if (rel_size == 0)
3014+ rel_addr = addr;
3015+ rel_size += s->sh_size;
3016+#endif
3017+ }
3018+ addr += s->sh_size;
3019+ if (s->sh_type != SHT_NOBITS)
3020+ file_offset += s->sh_size;
3021+ }
3022+ }
3023+ ph->p_filesz = file_offset - ph->p_offset;
3024+ ph->p_memsz = addr - ph->p_vaddr;
3025+ ph++;
3026+ if (j == 0) {
3027+ if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
3028+ /* if in the middle of a page, we duplicate the page in
3029+ memory so that one copy is RX and the other is RW */
3030+ if ((addr & (s1->section_align - 1)) != 0)
3031+ addr += s1->section_align;
3032+ } else {
3033+ addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
3034+ file_offset = (file_offset + s1->section_align - 1) &
3035+ ~(s1->section_align - 1);
3036+ }
3037+ }
3038+ }
3039+
3040+ /* if interpreter, then add corresponing program header */
3041+ if (interp) {
3042+ ph = &phdr[0];
3043+
3044+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
3045+ {
3046+ int len = phnum * sizeof(ElfW(Phdr));
3047+
3048+ ph->p_type = PT_PHDR;
3049+ ph->p_offset = sizeof(ElfW(Ehdr));
3050+ ph->p_vaddr = interp->sh_addr - len;
3051+ ph->p_paddr = ph->p_vaddr;
3052+ ph->p_filesz = ph->p_memsz = len;
3053+ ph->p_flags = PF_R | PF_X;
3054+ ph->p_align = 4; // interp->sh_addralign;
3055+ ph++;
3056+ }
3057+#endif
3058+
3059+ ph->p_type = PT_INTERP;
3060+ ph->p_offset = interp->sh_offset;
3061+ ph->p_vaddr = interp->sh_addr;
3062+ ph->p_paddr = ph->p_vaddr;
3063+ ph->p_filesz = interp->sh_size;
3064+ ph->p_memsz = interp->sh_size;
3065+ ph->p_flags = PF_R;
3066+ ph->p_align = interp->sh_addralign;
3067+ }
3068+
3069+ /* if dynamic section, then add corresponing program header */
3070+ if (dynamic) {
3071+ ElfW(Sym) *sym_end;
3072+
3073+ ph = &phdr[phnum - 1];
3074+
3075+ ph->p_type = PT_DYNAMIC;
3076+ ph->p_offset = dynamic->sh_offset;
3077+ ph->p_vaddr = dynamic->sh_addr;
3078+ ph->p_paddr = ph->p_vaddr;
3079+ ph->p_filesz = dynamic->sh_size;
3080+ ph->p_memsz = dynamic->sh_size;
3081+ ph->p_flags = PF_R | PF_W;
3082+ ph->p_align = dynamic->sh_addralign;
3083+
3084+ /* put GOT dynamic section address */
3085+ put32(s1->got->data, dynamic->sh_addr);
3086+
3087+ /* relocate the PLT */
3088+ if (file_type == TCC_OUTPUT_EXE
3089+#if defined(TCC_OUTPUT_DLL_WITH_PLT)
3090+ || file_type == TCC_OUTPUT_DLL
3091+#endif
3092+ ) {
3093+ uint8_t *p, *p_end;
3094+
3095+ p = s1->plt->data;
3096+ p_end = p + s1->plt->data_offset;
3097+ if (p < p_end) {
3098+#if defined(TCC_TARGET_I386)
3099+ put32(p + 2, get32(p + 2) + s1->got->sh_addr);
3100+ put32(p + 8, get32(p + 8) + s1->got->sh_addr);
3101+ p += 16;
3102+ while (p < p_end) {
3103+ put32(p + 2, get32(p + 2) + s1->got->sh_addr);
3104+ p += 16;
3105+ }
3106+#elif defined(TCC_TARGET_X86_64)
3107+ int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
3108+ put32(p + 2, get32(p + 2) + x);
3109+ put32(p + 8, get32(p + 8) + x - 6);
3110+ p += 16;
3111+ while (p < p_end) {
3112+ put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
3113+ p += 16;
3114+ }
3115+#elif defined(TCC_TARGET_ARM)
3116+ int x;
3117+ x=s1->got->sh_addr - s1->plt->sh_addr - 12;
3118+ p +=16;
3119+ while (p < p_end) {
3120+ put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
3121+ p += 16;
3122+ }
3123+#elif defined(TCC_TARGET_C67)
3124+ /* XXX: TODO */
3125+#else
3126+#error unsupported CPU
3127+#endif
3128+ }
3129+ }
3130+
3131+ /* relocate symbols in .dynsym */
3132+ sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
3133+ for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
3134+ sym < sym_end;
3135+ sym++) {
3136+ if (sym->st_shndx == SHN_UNDEF) {
3137+ /* relocate to the PLT if the symbol corresponds
3138+ to a PLT entry */
3139+ if (sym->st_value)
3140+ sym->st_value += s1->plt->sh_addr;
3141+ } else if (sym->st_shndx < SHN_LORESERVE) {
3142+ /* do symbol relocation */
3143+ sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
3144+ }
3145+ }
3146+
3147+ /* put dynamic section entries */
3148+ dynamic->data_offset = saved_dynamic_data_offset;
3149+ put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
3150+ put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
3151+ put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
3152+ put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
3153+ put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
3154+#ifdef TCC_TARGET_X86_64
3155+ put_dt(dynamic, DT_RELA, rel_addr);
3156+ put_dt(dynamic, DT_RELASZ, rel_size);
3157+ put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
3158+#else
3159+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
3160+ put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
3161+ put_dt(dynamic, DT_PLTRELSZ, rel_size);
3162+ put_dt(dynamic, DT_JMPREL, rel_addr);
3163+ put_dt(dynamic, DT_PLTREL, DT_REL);
3164+ put_dt(dynamic, DT_REL, bss_addr);
3165+ put_dt(dynamic, DT_RELSZ, bss_size);
3166+#else
3167+ put_dt(dynamic, DT_REL, rel_addr);
3168+ put_dt(dynamic, DT_RELSZ, rel_size);
3169+ put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
3170+#endif
3171+#endif
3172+ if (s1->do_debug)
3173+ put_dt(dynamic, DT_DEBUG, 0);
3174+ put_dt(dynamic, DT_NULL, 0);
3175+ }
3176+
3177+ ehdr.e_phentsize = sizeof(ElfW(Phdr));
3178+ ehdr.e_phnum = phnum;
3179+ ehdr.e_phoff = sizeof(ElfW(Ehdr));
3180+ }
3181+
3182+ /* all other sections come after */
3183+ for(i = 1; i < s1->nb_sections; i++) {
3184+ s = s1->sections[i];
3185+ if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
3186+ continue;
3187+ section_order[sh_order_index++] = i;
3188+
3189+ file_offset = (file_offset + s->sh_addralign - 1) &
3190+ ~(s->sh_addralign - 1);
3191+ s->sh_offset = file_offset;
3192+ if (s->sh_type != SHT_NOBITS)
3193+ file_offset += s->sh_size;
3194+ }
3195+
3196+ /* if building executable or DLL, then relocate each section
3197+ except the GOT which is already relocated */
3198+ if (file_type != TCC_OUTPUT_OBJ) {
3199+ relocate_syms(s1, 0);
3200+
3201+ if (s1->nb_errors != 0) {
3202+ fail:
3203+ ret = -1;
3204+ goto the_end;
3205+ }
3206+
3207+ /* relocate sections */
3208+ /* XXX: ignore sections with allocated relocations ? */
3209+ for(i = 1; i < s1->nb_sections; i++) {
3210+ s = s1->sections[i];
3211+ if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
3212+ relocate_section(s1, s);
3213+ }
3214+
3215+ /* relocate relocation entries if the relocation tables are
3216+ allocated in the executable */
3217+ for(i = 1; i < s1->nb_sections; i++) {
3218+ s = s1->sections[i];
3219+ if ((s->sh_flags & SHF_ALLOC) &&
3220+ s->sh_type == SHT_RELX) {
3221+ relocate_rel(s1, s);
3222+ }
3223+ }
3224+
3225+ /* get entry point address */
3226+ if (file_type == TCC_OUTPUT_EXE)
3227+ ehdr.e_entry = (uplong)tcc_get_symbol_err(s1, "_start");
3228+ else
3229+ ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
3230+ }
3231+ if (file_type == TCC_OUTPUT_EXE && s1->static_link)
3232+ fill_got(s1);
3233+
3234+ /* write elf file */
3235+ if (file_type == TCC_OUTPUT_OBJ)
3236+ mode = 0666;
3237+ else
3238+ mode = 0777;
3239+ unlink(filename);
3240+ fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
3241+ if (fd < 0) {
3242+ tcc_error_noabort("could not write '%s'", filename);
3243+ goto fail;
3244+ }
3245+ f = fdopen(fd, "wb");
3246+ if (s1->verbose)
3247+ printf("<- %s\n", filename);
3248+
3249+#ifdef TCC_TARGET_COFF
3250+ if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
3251+ tcc_output_coff(s1, f);
3252+ } else
3253+#endif
3254+ if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
3255+ sort_syms(s1, symtab_section);
3256+
3257+ /* align to 4 */
3258+ file_offset = (file_offset + 3) & -4;
3259+
3260+ /* fill header */
3261+ ehdr.e_ident[0] = ELFMAG0;
3262+ ehdr.e_ident[1] = ELFMAG1;
3263+ ehdr.e_ident[2] = ELFMAG2;
3264+ ehdr.e_ident[3] = ELFMAG3;
3265+ ehdr.e_ident[4] = ELFCLASSW;
3266+ ehdr.e_ident[5] = ELFDATA2LSB;
3267+ ehdr.e_ident[6] = EV_CURRENT;
3268+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
3269+ ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
3270+#endif
3271+#ifdef TCC_TARGET_ARM
3272+#ifdef TCC_ARM_EABI
3273+ ehdr.e_ident[EI_OSABI] = 0;
3274+ ehdr.e_flags = 4 << 24;
3275+#else
3276+ ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
3277+#endif
3278+#endif
3279+ switch(file_type) {
3280+ default:
3281+ case TCC_OUTPUT_EXE:
3282+ ehdr.e_type = ET_EXEC;
3283+ break;
3284+ case TCC_OUTPUT_DLL:
3285+ ehdr.e_type = ET_DYN;
3286+ break;
3287+ case TCC_OUTPUT_OBJ:
3288+ ehdr.e_type = ET_REL;
3289+ break;
3290+ }
3291+ ehdr.e_machine = EM_TCC_TARGET;
3292+ ehdr.e_version = EV_CURRENT;
3293+ ehdr.e_shoff = file_offset;
3294+ ehdr.e_ehsize = sizeof(ElfW(Ehdr));
3295+ ehdr.e_shentsize = sizeof(ElfW(Shdr));
3296+ ehdr.e_shnum = shnum;
3297+ ehdr.e_shstrndx = shnum - 1;
3298+
3299+ fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
3300+ fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
3301+ offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
3302+
3303+ for(i=1;i<s1->nb_sections;i++) {
3304+ s = s1->sections[section_order[i]];
3305+ if (s->sh_type != SHT_NOBITS) {
3306+ if (s->sh_type == SHT_DYNSYM)
3307+ patch_dynsym_undef(s1, s);
3308+ while (offset < s->sh_offset) {
3309+ fputc(0, f);
3310+ offset++;
3311+ }
3312+ size = s->sh_size;
3313+ fwrite(s->data, 1, size, f);
3314+ offset += size;
3315+ }
3316+ }
3317+
3318+ /* output section headers */
3319+ while (offset < ehdr.e_shoff) {
3320+ fputc(0, f);
3321+ offset++;
3322+ }
3323+
3324+ for(i=0;i<s1->nb_sections;i++) {
3325+ sh = &shdr;
3326+ memset(sh, 0, sizeof(ElfW(Shdr)));
3327+ s = s1->sections[i];
3328+ if (s) {
3329+ sh->sh_name = s->sh_name;
3330+ sh->sh_type = s->sh_type;
3331+ sh->sh_flags = s->sh_flags;
3332+ sh->sh_entsize = s->sh_entsize;
3333+ sh->sh_info = s->sh_info;
3334+ if (s->link)
3335+ sh->sh_link = s->link->sh_num;
3336+ sh->sh_addralign = s->sh_addralign;
3337+ sh->sh_addr = s->sh_addr;
3338+ sh->sh_offset = s->sh_offset;
3339+ sh->sh_size = s->sh_size;
3340+ }
3341+ fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
3342+ }
3343+ } else {
3344+ tcc_output_binary(s1, f, section_order);
3345+ }
3346+ fclose(f);
3347+
3348+ ret = 0;
3349+ the_end:
3350+ tcc_free(s1->symtab_to_dynsym);
3351+ tcc_free(section_order);
3352+ tcc_free(phdr);
3353+ tcc_free(s1->got_offsets);
3354+ return ret;
3355+}
3356+
3357+LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
3358+{
3359+ int ret;
3360+#ifdef TCC_TARGET_PE
3361+ if (s->output_type != TCC_OUTPUT_OBJ) {
3362+ ret = pe_output_file(s, filename);
3363+ } else
3364+#endif
3365+ {
3366+ ret = elf_output_file(s, filename);
3367+ }
3368+ return ret;
3369+}
3370+
3371+static void *load_data(int fd, unsigned long file_offset, unsigned long size)
3372+{
3373+ void *data;
3374+
3375+ data = tcc_malloc(size);
3376+ lseek(fd, file_offset, SEEK_SET);
3377+ read(fd, data, size);
3378+ return data;
3379+}
3380+
3381+typedef struct SectionMergeInfo {
3382+ Section *s; /* corresponding existing section */
3383+ unsigned long offset; /* offset of the new section in the existing section */
3384+ uint8_t new_section; /* true if section 's' was added */
3385+ uint8_t link_once; /* true if link once section */
3386+} SectionMergeInfo;
3387+
3388+/* load an object file and merge it with current files */
3389+/* XXX: handle correctly stab (debug) info */
3390+ST_FUNC int tcc_load_object_file(TCCState *s1,
3391+ int fd, unsigned long file_offset)
3392+{
3393+ ElfW(Ehdr) ehdr;
3394+ ElfW(Shdr) *shdr, *sh;
3395+ int size, i, j, offset, offseti, nb_syms, sym_index, ret;
3396+ unsigned char *strsec, *strtab;
3397+ int *old_to_new_syms;
3398+ char *sh_name, *name;
3399+ SectionMergeInfo *sm_table, *sm;
3400+ ElfW(Sym) *sym, *symtab;
3401+ ElfW_Rel *rel, *rel_end;
3402+ Section *s;
3403+
3404+ int stab_index;
3405+ int stabstr_index;
3406+
3407+ stab_index = stabstr_index = 0;
3408+
3409+ if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
3410+ goto fail1;
3411+ if (ehdr.e_ident[0] != ELFMAG0 ||
3412+ ehdr.e_ident[1] != ELFMAG1 ||
3413+ ehdr.e_ident[2] != ELFMAG2 ||
3414+ ehdr.e_ident[3] != ELFMAG3)
3415+ goto fail1;
3416+ /* test if object file */
3417+ if (ehdr.e_type != ET_REL)
3418+ goto fail1;
3419+ /* test CPU specific stuff */
3420+ if (ehdr.e_ident[5] != ELFDATA2LSB ||
3421+ ehdr.e_machine != EM_TCC_TARGET) {
3422+ fail1:
3423+ tcc_error_noabort("invalid object file");
3424+ return -1;
3425+ }
3426+ /* read sections */
3427+ shdr = load_data(fd, file_offset + ehdr.e_shoff,
3428+ sizeof(ElfW(Shdr)) * ehdr.e_shnum);
3429+ sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
3430+
3431+ /* load section names */
3432+ sh = &shdr[ehdr.e_shstrndx];
3433+ strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
3434+
3435+ /* load symtab and strtab */
3436+ old_to_new_syms = NULL;
3437+ symtab = NULL;
3438+ strtab = NULL;
3439+ nb_syms = 0;
3440+ for(i = 1; i < ehdr.e_shnum; i++) {
3441+ sh = &shdr[i];
3442+ if (sh->sh_type == SHT_SYMTAB) {
3443+ if (symtab) {
3444+ tcc_error_noabort("object must contain only one symtab");
3445+ fail:
3446+ ret = -1;
3447+ goto the_end;
3448+ }
3449+ nb_syms = sh->sh_size / sizeof(ElfW(Sym));
3450+ symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
3451+ sm_table[i].s = symtab_section;
3452+
3453+ /* now load strtab */
3454+ sh = &shdr[sh->sh_link];
3455+ strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
3456+ }
3457+ }
3458+
3459+ /* now examine each section and try to merge its content with the
3460+ ones in memory */
3461+ for(i = 1; i < ehdr.e_shnum; i++) {
3462+ /* no need to examine section name strtab */
3463+ if (i == ehdr.e_shstrndx)
3464+ continue;
3465+ sh = &shdr[i];
3466+ sh_name = strsec + sh->sh_name;
3467+ /* ignore sections types we do not handle */
3468+ if (sh->sh_type != SHT_PROGBITS &&
3469+ sh->sh_type != SHT_RELX &&
3470+#ifdef TCC_ARM_EABI
3471+ sh->sh_type != SHT_ARM_EXIDX &&
3472+#endif
3473+ sh->sh_type != SHT_NOBITS &&
3474+ sh->sh_type != SHT_PREINIT_ARRAY &&
3475+ sh->sh_type != SHT_INIT_ARRAY &&
3476+ sh->sh_type != SHT_FINI_ARRAY &&
3477+ strcmp(sh_name, ".stabstr")
3478+ )
3479+ continue;
3480+ if (sh->sh_addralign < 1)
3481+ sh->sh_addralign = 1;
3482+ /* find corresponding section, if any */
3483+ for(j = 1; j < s1->nb_sections;j++) {
3484+ s = s1->sections[j];
3485+ if (!strcmp(s->name, sh_name)) {
3486+ if (!strncmp(sh_name, ".gnu.linkonce",
3487+ sizeof(".gnu.linkonce") - 1)) {
3488+ /* if a 'linkonce' section is already present, we
3489+ do not add it again. It is a little tricky as
3490+ symbols can still be defined in
3491+ it. */
3492+ sm_table[i].link_once = 1;
3493+ goto next;
3494+ } else {
3495+ goto found;
3496+ }
3497+ }
3498+ }
3499+ /* not found: create new section */
3500+ s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
3501+ /* take as much info as possible from the section. sh_link and
3502+ sh_info will be updated later */
3503+ s->sh_addralign = sh->sh_addralign;
3504+ s->sh_entsize = sh->sh_entsize;
3505+ sm_table[i].new_section = 1;
3506+ found:
3507+ if (sh->sh_type != s->sh_type) {
3508+ tcc_error_noabort("invalid section type");
3509+ goto fail;
3510+ }
3511+
3512+ /* align start of section */
3513+ offset = s->data_offset;
3514+
3515+ if (0 == strcmp(sh_name, ".stab")) {
3516+ stab_index = i;
3517+ goto no_align;
3518+ }
3519+ if (0 == strcmp(sh_name, ".stabstr")) {
3520+ stabstr_index = i;
3521+ goto no_align;
3522+ }
3523+
3524+ size = sh->sh_addralign - 1;
3525+ offset = (offset + size) & ~size;
3526+ if (sh->sh_addralign > s->sh_addralign)
3527+ s->sh_addralign = sh->sh_addralign;
3528+ s->data_offset = offset;
3529+ no_align:
3530+ sm_table[i].offset = offset;
3531+ sm_table[i].s = s;
3532+ /* concatenate sections */
3533+ size = sh->sh_size;
3534+ if (sh->sh_type != SHT_NOBITS) {
3535+ unsigned char *ptr;
3536+ lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
3537+ ptr = section_ptr_add(s, size);
3538+ read(fd, ptr, size);
3539+ } else {
3540+ s->data_offset += size;
3541+ }
3542+ next: ;
3543+ }
3544+
3545+ /* //gr relocate stab strings */
3546+ if (stab_index && stabstr_index) {
3547+ Stab_Sym *a, *b;
3548+ unsigned o;
3549+ s = sm_table[stab_index].s;
3550+ a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
3551+ b = (Stab_Sym *)(s->data + s->data_offset);
3552+ o = sm_table[stabstr_index].offset;
3553+ while (a < b)
3554+ a->n_strx += o, a++;
3555+ }
3556+
3557+ /* second short pass to update sh_link and sh_info fields of new
3558+ sections */
3559+ for(i = 1; i < ehdr.e_shnum; i++) {
3560+ s = sm_table[i].s;
3561+ if (!s || !sm_table[i].new_section)
3562+ continue;
3563+ sh = &shdr[i];
3564+ if (sh->sh_link > 0)
3565+ s->link = sm_table[sh->sh_link].s;
3566+ if (sh->sh_type == SHT_RELX) {
3567+ s->sh_info = sm_table[sh->sh_info].s->sh_num;
3568+ /* update backward link */
3569+ s1->sections[s->sh_info]->reloc = s;
3570+ }
3571+ }
3572+ sm = sm_table;
3573+
3574+ /* resolve symbols */
3575+ old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
3576+
3577+ sym = symtab + 1;
3578+ for(i = 1; i < nb_syms; i++, sym++) {
3579+ if (sym->st_shndx != SHN_UNDEF &&
3580+ sym->st_shndx < SHN_LORESERVE) {
3581+ sm = &sm_table[sym->st_shndx];
3582+ if (sm->link_once) {
3583+ /* if a symbol is in a link once section, we use the
3584+ already defined symbol. It is very important to get
3585+ correct relocations */
3586+ if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
3587+ name = strtab + sym->st_name;
3588+ sym_index = find_elf_sym(symtab_section, name);
3589+ if (sym_index)
3590+ old_to_new_syms[i] = sym_index;
3591+ }
3592+ continue;
3593+ }
3594+ /* if no corresponding section added, no need to add symbol */
3595+ if (!sm->s)
3596+ continue;
3597+ /* convert section number */
3598+ sym->st_shndx = sm->s->sh_num;
3599+ /* offset value */
3600+ sym->st_value += sm->offset;
3601+ }
3602+ /* add symbol */
3603+ name = strtab + sym->st_name;
3604+ sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
3605+ sym->st_info, sym->st_other,
3606+ sym->st_shndx, name);
3607+ old_to_new_syms[i] = sym_index;
3608+ }
3609+
3610+ /* third pass to patch relocation entries */
3611+ for(i = 1; i < ehdr.e_shnum; i++) {
3612+ s = sm_table[i].s;
3613+ if (!s)
3614+ continue;
3615+ sh = &shdr[i];
3616+ offset = sm_table[i].offset;
3617+ switch(s->sh_type) {
3618+ case SHT_RELX:
3619+ /* take relocation offset information */
3620+ offseti = sm_table[sh->sh_info].offset;
3621+ rel_end = (ElfW_Rel *)(s->data + s->data_offset);
3622+ for(rel = (ElfW_Rel *)(s->data + offset);
3623+ rel < rel_end;
3624+ rel++) {
3625+ int type;
3626+ unsigned sym_index;
3627+ /* convert symbol index */
3628+ type = ELFW(R_TYPE)(rel->r_info);
3629+ sym_index = ELFW(R_SYM)(rel->r_info);
3630+ /* NOTE: only one symtab assumed */
3631+ if (sym_index >= nb_syms)
3632+ goto invalid_reloc;
3633+ sym_index = old_to_new_syms[sym_index];
3634+ /* ignore link_once in rel section. */
3635+ if (!sym_index && !sm->link_once
3636+#ifdef TCC_TARGET_ARM
3637+ && type != R_ARM_V4BX
3638+#endif
3639+ ) {
3640+ invalid_reloc:
3641+ tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
3642+ i, strsec + sh->sh_name, rel->r_offset);
3643+ goto fail;
3644+ }
3645+ rel->r_info = ELFW(R_INFO)(sym_index, type);
3646+ /* offset the relocation offset */
3647+ rel->r_offset += offseti;
3648+ }
3649+ break;
3650+ default:
3651+ break;
3652+ }
3653+ }
3654+
3655+ ret = 0;
3656+ the_end:
3657+ tcc_free(symtab);
3658+ tcc_free(strtab);
3659+ tcc_free(old_to_new_syms);
3660+ tcc_free(sm_table);
3661+ tcc_free(strsec);
3662+ tcc_free(shdr);
3663+ return ret;
3664+}
3665+
3666+typedef struct ArchiveHeader {
3667+ char ar_name[16]; /* name of this member */
3668+ char ar_date[12]; /* file mtime */
3669+ char ar_uid[6]; /* owner uid; printed as decimal */
3670+ char ar_gid[6]; /* owner gid; printed as decimal */
3671+ char ar_mode[8]; /* file mode, printed as octal */
3672+ char ar_size[10]; /* file size, printed as decimal */
3673+ char ar_fmag[2]; /* should contain ARFMAG */
3674+} ArchiveHeader;
3675+
3676+static int get_be32(const uint8_t *b)
3677+{
3678+ return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
3679+}
3680+
3681+/* load only the objects which resolve undefined symbols */
3682+static int tcc_load_alacarte(TCCState *s1, int fd, int size)
3683+{
3684+ int i, bound, nsyms, sym_index, off, ret;
3685+ uint8_t *data;
3686+ const char *ar_names, *p;
3687+ const uint8_t *ar_index;
3688+ ElfW(Sym) *sym;
3689+
3690+ data = tcc_malloc(size);
3691+ if (read(fd, data, size) != size)
3692+ goto fail;
3693+ nsyms = get_be32(data);
3694+ ar_index = data + 4;
3695+ ar_names = ar_index + nsyms * 4;
3696+
3697+ do {
3698+ bound = 0;
3699+ for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
3700+ sym_index = find_elf_sym(symtab_section, p);
3701+ if(sym_index) {
3702+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
3703+ if(sym->st_shndx == SHN_UNDEF) {
3704+ off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
3705+#if 0
3706+ printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
3707+#endif
3708+ ++bound;
3709+ lseek(fd, off, SEEK_SET);
3710+ if(tcc_load_object_file(s1, fd, off) < 0) {
3711+ fail:
3712+ ret = -1;
3713+ goto the_end;
3714+ }
3715+ }
3716+ }
3717+ }
3718+ } while(bound);
3719+ ret = 0;
3720+ the_end:
3721+ tcc_free(data);
3722+ return ret;
3723+}
3724+
3725+/* load a '.a' file */
3726+ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
3727+{
3728+ ArchiveHeader hdr;
3729+ char ar_size[11];
3730+ char ar_name[17];
3731+ char magic[8];
3732+ int size, len, i;
3733+ unsigned long file_offset;
3734+
3735+ /* skip magic which was already checked */
3736+ read(fd, magic, sizeof(magic));
3737+
3738+ for(;;) {
3739+ len = read(fd, &hdr, sizeof(hdr));
3740+ if (len == 0)
3741+ break;
3742+ if (len != sizeof(hdr)) {
3743+ tcc_error_noabort("invalid archive");
3744+ return -1;
3745+ }
3746+ memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
3747+ ar_size[sizeof(hdr.ar_size)] = '\0';
3748+ size = strtol(ar_size, NULL, 0);
3749+ memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
3750+ for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
3751+ if (ar_name[i] != ' ')
3752+ break;
3753+ }
3754+ ar_name[i + 1] = '\0';
3755+ // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
3756+ file_offset = lseek(fd, 0, SEEK_CUR);
3757+ /* align to even */
3758+ size = (size + 1) & ~1;
3759+ if (!strcmp(ar_name, "/")) {
3760+ /* coff symbol table : we handle it */
3761+ if(s1->alacarte_link)
3762+ return tcc_load_alacarte(s1, fd, size);
3763+ } else if (!strcmp(ar_name, "//") ||
3764+ !strcmp(ar_name, "__.SYMDEF") ||
3765+ !strcmp(ar_name, "__.SYMDEF/") ||
3766+ !strcmp(ar_name, "ARFILENAMES/")) {
3767+ /* skip symbol table or archive names */
3768+ } else {
3769+ if (tcc_load_object_file(s1, fd, file_offset) < 0)
3770+ return -1;
3771+ }
3772+ lseek(fd, file_offset + size, SEEK_SET);
3773+ }
3774+ return 0;
3775+}
3776+
3777+#ifndef TCC_TARGET_PE
3778+/* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
3779+ is referenced by the user (so it should be added as DT_NEEDED in
3780+ the generated ELF file) */
3781+ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
3782+{
3783+ ElfW(Ehdr) ehdr;
3784+ ElfW(Shdr) *shdr, *sh, *sh1;
3785+ int i, j, nb_syms, nb_dts, sym_bind, ret;
3786+ ElfW(Sym) *sym, *dynsym;
3787+ ElfW(Dyn) *dt, *dynamic;
3788+ unsigned char *dynstr;
3789+ const char *name, *soname;
3790+ DLLReference *dllref;
3791+
3792+ read(fd, &ehdr, sizeof(ehdr));
3793+
3794+ /* test CPU specific stuff */
3795+ if (ehdr.e_ident[5] != ELFDATA2LSB ||
3796+ ehdr.e_machine != EM_TCC_TARGET) {
3797+ tcc_error_noabort("bad architecture");
3798+ return -1;
3799+ }
3800+
3801+ /* read sections */
3802+ shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
3803+
3804+ /* load dynamic section and dynamic symbols */
3805+ nb_syms = 0;
3806+ nb_dts = 0;
3807+ dynamic = NULL;
3808+ dynsym = NULL; /* avoid warning */
3809+ dynstr = NULL; /* avoid warning */
3810+ for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
3811+ switch(sh->sh_type) {
3812+ case SHT_DYNAMIC:
3813+ nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
3814+ dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
3815+ break;
3816+ case SHT_DYNSYM:
3817+ nb_syms = sh->sh_size / sizeof(ElfW(Sym));
3818+ dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
3819+ sh1 = &shdr[sh->sh_link];
3820+ dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
3821+ break;
3822+ default:
3823+ break;
3824+ }
3825+ }
3826+
3827+ /* compute the real library name */
3828+ soname = tcc_basename(filename);
3829+
3830+ for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
3831+ if (dt->d_tag == DT_SONAME) {
3832+ soname = dynstr + dt->d_un.d_val;
3833+ }
3834+ }
3835+
3836+ /* if the dll is already loaded, do not load it */
3837+ for(i = 0; i < s1->nb_loaded_dlls; i++) {
3838+ dllref = s1->loaded_dlls[i];
3839+ if (!strcmp(soname, dllref->name)) {
3840+ /* but update level if needed */
3841+ if (level < dllref->level)
3842+ dllref->level = level;
3843+ ret = 0;
3844+ goto the_end;
3845+ }
3846+ }
3847+
3848+ // printf("loading dll '%s'\n", soname);
3849+
3850+ /* add the dll and its level */
3851+ dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
3852+ dllref->level = level;
3853+ strcpy(dllref->name, soname);
3854+ dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
3855+
3856+ /* add dynamic symbols in dynsym_section */
3857+ for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
3858+ sym_bind = ELFW(ST_BIND)(sym->st_info);
3859+ if (sym_bind == STB_LOCAL)
3860+ continue;
3861+ name = dynstr + sym->st_name;
3862+ add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
3863+ sym->st_info, sym->st_other, sym->st_shndx, name);
3864+ }
3865+
3866+ /* load all referenced DLLs */
3867+ for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
3868+ switch(dt->d_tag) {
3869+ case DT_NEEDED:
3870+ name = dynstr + dt->d_un.d_val;
3871+ for(j = 0; j < s1->nb_loaded_dlls; j++) {
3872+ dllref = s1->loaded_dlls[j];
3873+ if (!strcmp(name, dllref->name))
3874+ goto already_loaded;
3875+ }
3876+ if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
3877+ tcc_error_noabort("referenced dll '%s' not found", name);
3878+ ret = -1;
3879+ goto the_end;
3880+ }
3881+ already_loaded:
3882+ break;
3883+ }
3884+ }
3885+ ret = 0;
3886+ the_end:
3887+ tcc_free(dynstr);
3888+ tcc_free(dynsym);
3889+ tcc_free(dynamic);
3890+ tcc_free(shdr);
3891+ return ret;
3892+}
3893+
3894+#define LD_TOK_NAME 256
3895+#define LD_TOK_EOF (-1)
3896+
3897+/* return next ld script token */
3898+static int ld_next(TCCState *s1, char *name, int name_size)
3899+{
3900+ int c;
3901+ char *q;
3902+
3903+ redo:
3904+ switch(ch) {
3905+ case ' ':
3906+ case '\t':
3907+ case '\f':
3908+ case '\v':
3909+ case '\r':
3910+ case '\n':
3911+ inp();
3912+ goto redo;
3913+ case '/':
3914+ minp();
3915+ if (ch == '*') {
3916+ file->buf_ptr = parse_comment(file->buf_ptr);
3917+ ch = file->buf_ptr[0];
3918+ goto redo;
3919+ } else {
3920+ q = name;
3921+ *q++ = '/';
3922+ goto parse_name;
3923+ }
3924+ break;
3925+ /* case 'a' ... 'z': */
3926+ case 'a':
3927+ case 'b':
3928+ case 'c':
3929+ case 'd':
3930+ case 'e':
3931+ case 'f':
3932+ case 'g':
3933+ case 'h':
3934+ case 'i':
3935+ case 'j':
3936+ case 'k':
3937+ case 'l':
3938+ case 'm':
3939+ case 'n':
3940+ case 'o':
3941+ case 'p':
3942+ case 'q':
3943+ case 'r':
3944+ case 's':
3945+ case 't':
3946+ case 'u':
3947+ case 'v':
3948+ case 'w':
3949+ case 'x':
3950+ case 'y':
3951+ case 'z':
3952+ /* case 'A' ... 'z': */
3953+ case 'A':
3954+ case 'B':
3955+ case 'C':
3956+ case 'D':
3957+ case 'E':
3958+ case 'F':
3959+ case 'G':
3960+ case 'H':
3961+ case 'I':
3962+ case 'J':
3963+ case 'K':
3964+ case 'L':
3965+ case 'M':
3966+ case 'N':
3967+ case 'O':
3968+ case 'P':
3969+ case 'Q':
3970+ case 'R':
3971+ case 'S':
3972+ case 'T':
3973+ case 'U':
3974+ case 'V':
3975+ case 'W':
3976+ case 'X':
3977+ case 'Y':
3978+ case 'Z':
3979+ case '_':
3980+ case '\\':
3981+ case '.':
3982+ case '$':
3983+ case '~':
3984+ q = name;
3985+ parse_name:
3986+ for(;;) {
3987+ if (!((ch >= 'a' && ch <= 'z') ||
3988+ (ch >= 'A' && ch <= 'Z') ||
3989+ (ch >= '0' && ch <= '9') ||
3990+ strchr("/.-_+=$:\\,~", ch)))
3991+ break;
3992+ if ((q - name) < name_size - 1) {
3993+ *q++ = ch;
3994+ }
3995+ minp();
3996+ }
3997+ *q = '\0';
3998+ c = LD_TOK_NAME;
3999+ break;
4000+ case CH_EOF:
4001+ c = LD_TOK_EOF;
4002+ break;
4003+ default:
4004+ c = ch;
4005+ inp();
4006+ break;
4007+ }
4008+#if 0
4009+ printf("tok=%c %d\n", c, c);
4010+ if (c == LD_TOK_NAME)
4011+ printf(" name=%s\n", name);
4012+#endif
4013+ return c;
4014+}
4015+
4016+/*
4017+ * Extract the file name from the library name
4018+ *
4019+ * /!\ No test on filename capacity, be careful
4020+ */
4021+static void libname_to_filename(TCCState *s1, const char libname[], char filename[])
4022+{
4023+ if (!s1->static_link) {
4024+ sprintf(filename, "lib%s.so", libname);
4025+ } else {
4026+ sprintf(filename, "lib%s.a", libname);
4027+ }
4028+}
4029+
4030+static int ld_add_file(TCCState *s1, const char filename[])
4031+{
4032+ int ret;
4033+
4034+ ret = tcc_add_file_internal(s1, filename, 0);
4035+ if (ret)
4036+ ret = tcc_add_dll(s1, filename, 0);
4037+ return ret;
4038+}
4039+
4040+static inline int new_undef_syms(void)
4041+{
4042+ int ret = 0;
4043+ ret = new_undef_sym;
4044+ new_undef_sym = 0;
4045+ return ret;
4046+}
4047+
4048+static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
4049+{
4050+ char filename[1024], libname[1024];
4051+ int t, group, nblibs = 0, ret = 0;
4052+ char **libs = NULL;
4053+
4054+ group = !strcmp(cmd, "GROUP");
4055+ if (!as_needed)
4056+ new_undef_syms();
4057+ t = ld_next(s1, filename, sizeof(filename));
4058+ if (t != '(')
4059+ expect("(");
4060+ t = ld_next(s1, filename, sizeof(filename));
4061+ for(;;) {
4062+ libname[0] = '\0';
4063+ if (t == LD_TOK_EOF) {
4064+ tcc_error_noabort("unexpected end of file");
4065+ ret = -1;
4066+ goto lib_parse_error;
4067+ } else if (t == ')') {
4068+ break;
4069+ } else if (t == '-') {
4070+ t = ld_next(s1, filename, sizeof(filename));
4071+ if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
4072+ tcc_error_noabort("library name expected");
4073+ ret = -1;
4074+ goto lib_parse_error;
4075+ }
4076+ strcpy(libname, &filename[1]);
4077+ libname_to_filename(s1, libname, filename);
4078+ } else if (t != LD_TOK_NAME) {
4079+ tcc_error_noabort("filename expected");
4080+ ret = -1;
4081+ goto lib_parse_error;
4082+ }
4083+ if (!strcmp(filename, "AS_NEEDED")) {
4084+ ret = ld_add_file_list(s1, cmd, 1);
4085+ if (ret)
4086+ goto lib_parse_error;
4087+ } else {
4088+ /* TODO: Implement AS_NEEDED support. Ignore it for now */
4089+ if (!as_needed) {
4090+ ret = ld_add_file(s1, filename);
4091+ if (ret)
4092+ goto lib_parse_error;
4093+ if (group) {
4094+ /* Add the filename *and* the libname to avoid future conversions */
4095+ dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
4096+ if (libname[0] != '\0')
4097+ dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
4098+ }
4099+ }
4100+ }
4101+ t = ld_next(s1, filename, sizeof(filename));
4102+ if (t == ',') {
4103+ t = ld_next(s1, filename, sizeof(filename));
4104+ }
4105+ }
4106+ if (group && !as_needed) {
4107+ while (new_undef_syms()) {
4108+ int i;
4109+
4110+ for (i = 0; i < nblibs; i ++)
4111+ ld_add_file(s1, libs[i]);
4112+ }
4113+ }
4114+lib_parse_error:
4115+ dynarray_reset(&libs, &nblibs);
4116+ return ret;
4117+}
4118+
4119+/* interpret a subset of GNU ldscripts to handle the dummy libc.so
4120+ files */
4121+ST_FUNC int tcc_load_ldscript(TCCState *s1)
4122+{
4123+ char cmd[64];
4124+ char filename[1024];
4125+ int t, ret;
4126+
4127+ ch = file->buf_ptr[0];
4128+ ch = handle_eob();
4129+ for(;;) {
4130+ t = ld_next(s1, cmd, sizeof(cmd));
4131+ if (t == LD_TOK_EOF)
4132+ return 0;
4133+ else if (t != LD_TOK_NAME)
4134+ return -1;
4135+ if (!strcmp(cmd, "INPUT") ||
4136+ !strcmp(cmd, "GROUP")) {
4137+ ret = ld_add_file_list(s1, cmd, 0);
4138+ if (ret)
4139+ return ret;
4140+ } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
4141+ !strcmp(cmd, "TARGET")) {
4142+ /* ignore some commands */
4143+ t = ld_next(s1, cmd, sizeof(cmd));
4144+ if (t != '(')
4145+ expect("(");
4146+ for(;;) {
4147+ t = ld_next(s1, filename, sizeof(filename));
4148+ if (t == LD_TOK_EOF) {
4149+ tcc_error_noabort("unexpected end of file");
4150+ return -1;
4151+ } else if (t == ')') {
4152+ break;
4153+ }
4154+ }
4155+ } else {
4156+ return -1;
4157+ }
4158+ }
4159+ return 0;
4160+}
4161+#endif /* ndef TCC_TARGET_PE */
4162
4163=== added directory '.pc/0002-Evaluate-configure-arguments.patch'
4164=== added file '.pc/0002-Evaluate-configure-arguments.patch/configure'
4165--- .pc/0002-Evaluate-configure-arguments.patch/configure 1970-01-01 00:00:00 +0000
4166+++ .pc/0002-Evaluate-configure-arguments.patch/configure 2012-11-13 09:46:40 +0000
4167@@ -0,0 +1,496 @@
4168+#!/bin/sh
4169+#
4170+# tcc configure script (c) 2003 Fabrice Bellard
4171+
4172+# set temporary file name
4173+if test ! -z "$TMPDIR" ; then
4174+ TMPDIR1="${TMPDIR}"
4175+elif test ! -z "$TEMPDIR" ; then
4176+ TMPDIR1="${TEMPDIR}"
4177+else
4178+ TMPDIR1="/tmp"
4179+fi
4180+
4181+# bashism: TMPN="${TMPDIR1}/tcc-conf-${RANDOM}-$$-${RANDOM}.c"
4182+TMPN="./conftest-$$"
4183+
4184+TMPC=$TMPN.c
4185+TMPH=$TMPN.h
4186+TMPO=$TMPN.o
4187+TMPE=$TMPN
4188+
4189+# default parameters
4190+build_cross="no"
4191+use_libgcc="no"
4192+prefix=""
4193+execprefix=""
4194+bindir=""
4195+libdir=""
4196+tccdir=""
4197+includedir=""
4198+mandir=""
4199+infodir=""
4200+sysroot=""
4201+cross_prefix=""
4202+cc="gcc"
4203+host_cc="gcc"
4204+ar="ar"
4205+strip="strip"
4206+cygwin="no"
4207+cpu=`uname -m`
4208+
4209+tcc_sysincludepaths=""
4210+tcc_libpaths=""
4211+tcc_crtprefix=""
4212+tcc_elfinterp=""
4213+
4214+case "$cpu" in
4215+ i386|i486|i586|i686|i86pc|BePC|i686-AT386)
4216+ cpu="x86"
4217+ ;;
4218+ x86_64)
4219+ cpu="x86-64"
4220+ ;;
4221+ arm|armv4l|armv5tel|armv5tejl|armv6j|armv7a|armv7l)
4222+ cpu="armv4l"
4223+ ;;
4224+ alpha)
4225+ cpu="alpha"
4226+ ;;
4227+ "Power Macintosh"|ppc|ppc64)
4228+ cpu="powerpc"
4229+ ;;
4230+ mips)
4231+ cpu="mips"
4232+ ;;
4233+ s390)
4234+ cpu="s390"
4235+ ;;
4236+ *)
4237+ cpu="unknown"
4238+ ;;
4239+esac
4240+gprof="no"
4241+bigendian="no"
4242+mingw32="no"
4243+LIBSUF=".a"
4244+EXESUF=""
4245+
4246+# OS specific
4247+targetos=`uname -s`
4248+case $targetos in
4249+MINGW32*)
4250+mingw32="yes"
4251+;;
4252+DragonFly)
4253+noldl="yes"
4254+;;
4255+OpenBSD)
4256+noldl="yes"
4257+;;
4258+*) ;;
4259+esac
4260+
4261+# find source path
4262+# XXX: we assume an absolute path is given when launching configure,
4263+# except in './configure' case.
4264+source_path=${0%configure}
4265+source_path=${source_path%/}
4266+source_path_used="yes"
4267+if test -z "$source_path" -o "$source_path" = "." ; then
4268+ source_path=`pwd`
4269+ source_path_used="no"
4270+fi
4271+
4272+for opt do
4273+ case "$opt" in
4274+ --prefix=*) prefix=`echo $opt | cut -d '=' -f 2`
4275+ ;;
4276+ --exec-prefix=*) execprefix=`echo $opt | cut -d '=' -f 2`
4277+ ;;
4278+ --tccdir=*) tccdir=`echo $opt | cut -d '=' -f 2`
4279+ ;;
4280+ --bindir=*) bindir=`echo $opt | cut -d '=' -f 2`
4281+ ;;
4282+ --libdir=*) libdir=`echo $opt | cut -d '=' -f 2`
4283+ ;;
4284+ --includedir=*) includedir=`echo $opt | cut -d '=' -f 2`
4285+ ;;
4286+ --sharedir=*) sharedir=`echo $opt | cut -d '=' -f 2`
4287+ ;;
4288+ --mandir=*) mandir=`echo $opt | cut -d '=' -f 2`
4289+ ;;
4290+ --infodir=*) infodir=`echo $opt | cut -d '=' -f 2`
4291+ ;;
4292+ --docdir=*) docdir=`echo $opt | cut -d '=' -f 2`
4293+ ;;
4294+ --sysroot=*) sysroot=`echo $opt | cut -d '=' -f 2`
4295+ ;;
4296+ --source-path=*) source_path=`echo $opt | cut -d '=' -f 2`
4297+ ;;
4298+ --cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2`
4299+ ;;
4300+ --cc=*) cc=`echo $opt | cut -d '=' -f 2`
4301+ ;;
4302+ --extra-cflags=*) CFLAGS="${opt#--extra-cflags=}"
4303+ ;;
4304+ --extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}"
4305+ ;;
4306+ --extra-libs=*) extralibs=${opt#--extra-libs=}
4307+ ;;
4308+ --sysincludepaths=*) tcc_sysincludepaths=`echo $opt | cut -d '=' -f 2`
4309+ ;;
4310+ --libpaths=*) tcc_libpaths=`echo $opt | cut -d '=' -f 2`
4311+ ;;
4312+ --crtprefix=*) tcc_crtprefix=`echo $opt | cut -d '=' -f 2`
4313+ ;;
4314+ --elfinterp=*) tcc_elfinterp=`echo $opt | cut -d '=' -f 2`
4315+ ;;
4316+ --cpu=*) cpu=`echo $opt | cut -d '=' -f 2`
4317+ ;;
4318+ --enable-gprof) gprof="yes"
4319+ ;;
4320+ --enable-mingw32) mingw32="yes" ; cross_prefix="i686-pc-mingw32-" ; cpu=x86
4321+ ;;
4322+ --enable-cygwin) mingw32="yes" ; cygwin="yes" ; cross_prefix="mingw32-" ; cpu=x86
4323+ ;;
4324+ --enable-cross) build_cross="yes"
4325+ ;;
4326+ --disable-static) disable_static="yes"
4327+ ;;
4328+ --disable-rpath) disable_rpath="yes"
4329+ ;;
4330+ --strip-binaries) strip_binaries="yes"
4331+ ;;
4332+ --with-libgcc) use_libgcc="yes"
4333+ ;;
4334+ --with-selinux) have_selinux="yes"
4335+ ;;
4336+ --help|-h) show_help="yes"
4337+ ;;
4338+ *) echo "configure: WARNING: unrecognized option $opt"
4339+ ;;
4340+ esac
4341+done
4342+
4343+# Checking for CFLAGS
4344+if test -z "$CFLAGS"; then
4345+ CFLAGS="-Wall -g -O2"
4346+fi
4347+
4348+cc="${cross_prefix}${cc}"
4349+ar="${cross_prefix}${ar}"
4350+strip="${cross_prefix}${strip}"
4351+
4352+if test "$mingw32" = "yes" ; then
4353+ LIBSUF=".lib"
4354+ EXESUF=".exe"
4355+fi
4356+
4357+if test -z "$cross_prefix" ; then
4358+
4359+# ---
4360+# big/little endian test
4361+cat > $TMPC << EOF
4362+#include <inttypes.h>
4363+int main(int argc, char ** argv){
4364+ volatile uint32_t i=0x01234567;
4365+ return (*((uint8_t*)(&i))) == 0x67;
4366+}
4367+EOF
4368+
4369+if $cc -o $TMPE $TMPC 2>/dev/null ; then
4370+ $TMPE && bigendian="yes"
4371+else
4372+ echo big/little test failed
4373+fi
4374+
4375+else
4376+
4377+# if cross compiling, cannot launch a program, so make a static guess
4378+if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" ; then
4379+ bigendian="yes"
4380+fi
4381+
4382+fi
4383+
4384+# check gcc version
4385+cat > $TMPC <<EOF
4386+int main(void) {
4387+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)
4388+return 0;
4389+#else
4390+#error gcc < 3.2
4391+#endif
4392+}
4393+EOF
4394+
4395+gcc_major="2"
4396+if $cc -o $TMPO $TMPC 2> /dev/null ; then
4397+ gcc_major="3"
4398+fi
4399+cat > $TMPC <<EOF
4400+int main(void) {
4401+#if __GNUC__ >= 4
4402+return 0;
4403+#else
4404+#error gcc < 4
4405+#endif
4406+}
4407+EOF
4408+
4409+if $cc -o $TMPO $TMPC 2> /dev/null ; then
4410+ gcc_major="4"
4411+fi
4412+
4413+if test x"$show_help" = "xyes" ; then
4414+cat << EOF
4415+
4416+Usage: configure [options]
4417+Options: [defaults in brackets after descriptions]
4418+
4419+EOF
4420+echo "Standard options:"
4421+echo " --help print this message"
4422+echo " --prefix=PREFIX install in PREFIX [$prefix]"
4423+echo " --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX"
4424+echo " [same as prefix]"
4425+echo " --bindir=DIR user executables in DIR [EPREFIX/bin]"
4426+echo " --libdir=DIR object code libraries in DIR [EPREFIX/lib]"
4427+echo " --tccdir=DIR installation directory [EPREFIX/lib/tcc]"
4428+echo " --includedir=DIR C header files in DIR [PREFIX/include]"
4429+echo " --sharedir=DIR documentation root DIR [PREFIX]/share"
4430+echo " --docdir=DIR documentation in DIR [SHAREDIR/doc/tcc]"
4431+echo " --mandir=DIR man documentation in DIR [SHAREDIR/man]"
4432+echo " --infodir=DIR info documentation in DIR [SHAREDIR/info]"
4433+echo ""
4434+echo "Advanced options (experts only):"
4435+echo " --source-path=PATH path of source code [$source_path]"
4436+echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]"
4437+echo " --sysroot=PREFIX prepend PREFIX to library/include paths []"
4438+echo " --cc=CC use C compiler CC [$cc]"
4439+echo " --disable-static make libtcc.so instead of libtcc.a"
4440+echo " --disable-rpath disable use of -rpath with the above"
4441+echo " --strip-binaries strip symbol tables from resulting binaries"
4442+echo " --with-libgcc use /lib/libgcc_s.so.1 instead of libtcc.a"
4443+echo " --enable-mingw32 build windows version on linux with mingw32"
4444+echo " --enable-cygwin build windows version on windows with cygwin"
4445+echo " [requires cygwin and mingw32-make]"
4446+echo " --enable-cross build cross compilers"
4447+echo " --extra-cflags= extra compiler flags"
4448+echo " --extra-ldflags= extra linker options"
4449+echo " --with-selinux use mmap instead of exec mem"
4450+echo " [requires write access to /tmp]"
4451+echo " --sysincludepaths=... specify system include paths, colon separated"
4452+echo " --libpaths=... specify system library paths, colon separated"
4453+echo " --crtprefix=... specify locations of crt?.o, colon separated"
4454+echo " --elfinterp=... specify elf interpreter"
4455+echo ""
4456+#echo "NOTE: The object files are build at the place where configure is launched"
4457+exit 1
4458+fi
4459+
4460+if test "$mingw32" = "yes" ; then
4461+ if test x"$tccdir" = x""; then
4462+ tccdir="tcc"
4463+ fi
4464+ if test -z "$prefix" ; then
4465+ prefix="C:/Program Files/${tccdir}"
4466+ fi
4467+ if test -z "$sharedir" ; then
4468+ sharedir="${prefix}"
4469+ fi
4470+ execprefix="$prefix"
4471+ bindir="${prefix}"
4472+ tccdir="${prefix}"
4473+ libdir="${prefix}/lib"
4474+ docdir="${sharedir}/doc"
4475+ mandir="${sharedir}/man"
4476+ infodir="${sharedir}/info"
4477+else
4478+ if test -z "$prefix" ; then
4479+ prefix="/usr/local"
4480+ fi
4481+ if test -z "$sharedir" ; then
4482+ sharedir="${prefix}/share"
4483+ fi
4484+ if test x"$execprefix" = x""; then
4485+ execprefix="${prefix}"
4486+ fi
4487+ if test x"$libdir" = x""; then
4488+ libdir="${execprefix}/lib"
4489+ fi
4490+ if test x"$bindir" = x""; then
4491+ bindir="${execprefix}/bin"
4492+ fi
4493+ if test x"$tccdir" = x""; then
4494+ tccdir="tcc"
4495+ fi
4496+ if test x"$docdir" = x""; then
4497+ docdir="${sharedir}/doc/${tccdir}"
4498+ fi
4499+ if test x"$mandir" = x""; then
4500+ mandir="${sharedir}/man"
4501+ fi
4502+ if test x"$infodir" = x""; then
4503+ infodir="${sharedir}/info"
4504+ fi
4505+ tccdir="${libdir}/${tccdir}"
4506+fi # mingw32
4507+
4508+if test x"$includedir" = x""; then
4509+includedir="${prefix}/include"
4510+fi
4511+
4512+echo "Binary directory $bindir"
4513+echo "TinyCC directory $tccdir"
4514+echo "Library directory $libdir"
4515+echo "Include directory $includedir"
4516+echo "Manual directory $mandir"
4517+echo "Info directory $infodir"
4518+echo "Doc directory $docdir"
4519+echo "Target root prefix $sysroot"
4520+echo "Source path $source_path"
4521+echo "C compiler $cc"
4522+echo "Target OS $targetos"
4523+echo "CPU $cpu"
4524+echo "Big Endian $bigendian"
4525+echo "gprof enabled $gprof"
4526+echo "cross compilers $build_cross"
4527+echo "use libgcc $use_libgcc"
4528+
4529+echo "Creating config.mak and config.h"
4530+
4531+echo "# Automatically generated by configure - do not modify" > config.mak
4532+echo "/* Automatically generated by configure - do not modify */" > $TMPH
4533+
4534+echo "prefix=$prefix" >> config.mak
4535+echo "bindir=\$(DESTDIR)$bindir" >> config.mak
4536+echo "tccdir=\$(DESTDIR)$tccdir" >> config.mak
4537+echo "libdir=\$(DESTDIR)$libdir" >> config.mak
4538+echo "ln_libdir=$libdir" >> config.mak
4539+echo "includedir=\$(DESTDIR)$includedir" >> config.mak
4540+echo "mandir=\$(DESTDIR)$mandir" >> config.mak
4541+echo "infodir=\$(DESTDIR)$infodir" >> config.mak
4542+echo "docdir=\$(DESTDIR)$docdir" >> config.mak
4543+print_var1()
4544+{
4545+ echo "#ifndef $1" >> $TMPH
4546+ echo "# define $1 \"$2\"" >> $TMPH
4547+ echo "#endif" >> $TMPH
4548+}
4549+print_var2()
4550+{
4551+ if test -n "$2"; then print_var1 $1 "$2"; fi
4552+}
4553+print_var2 CONFIG_SYSROOT "$sysroot"
4554+print_var1 CONFIG_TCCDIR "$tccdir"
4555+print_var2 CONFIG_TCC_SYSINCLUDEPATHS "$tcc_sysincludepaths"
4556+print_var2 CONFIG_TCC_LIBPATHS "$tcc_libpaths"
4557+print_var2 CONFIG_TCC_CRTPREFIX "$tcc_crtprefix"
4558+print_var2 CONFIG_TCC_ELFINTERP "$tcc_elfinterp"
4559+
4560+echo "CC=$cc" >> config.mak
4561+echo "GCC_MAJOR=$gcc_major" >> config.mak
4562+echo "#define GCC_MAJOR $gcc_major" >> $TMPH
4563+echo "HOST_CC=$host_cc" >> config.mak
4564+echo "AR=$ar" >> config.mak
4565+echo "STRIP=$strip -s -R .comment -R .note" >> config.mak
4566+echo "CFLAGS=$CFLAGS" >> config.mak
4567+echo "LDFLAGS=$LDFLAGS" >> config.mak
4568+echo "LIBSUF=$LIBSUF" >> config.mak
4569+echo "EXESUF=$EXESUF" >> config.mak
4570+
4571+if test "$cpu" = "x86" ; then
4572+ echo "ARCH=i386" >> config.mak
4573+ echo "#define HOST_I386 1" >> $TMPH
4574+elif test "$cpu" = "x86-64" ; then
4575+ echo "ARCH=x86-64" >> config.mak
4576+ echo "#define HOST_X86_64 1" >> $TMPH
4577+elif test "$cpu" = "armv4l" ; then
4578+ echo "ARCH=arm" >> config.mak
4579+ echo "#define HOST_ARM 1" >> $TMPH
4580+elif test "$cpu" = "powerpc" ; then
4581+ echo "ARCH=ppc" >> config.mak
4582+ echo "#define HOST_PPC 1" >> $TMPH
4583+elif test "$cpu" = "mips" ; then
4584+ echo "ARCH=mips" >> config.mak
4585+ echo "#define HOST_MIPS 1" >> $TMPH
4586+elif test "$cpu" = "s390" ; then
4587+ echo "ARCH=s390" >> config.mak
4588+ echo "#define HOST_S390 1" >> $TMPH
4589+elif test "$cpu" = "alpha" ; then
4590+ echo "ARCH=alpha" >> config.mak
4591+ echo "#define HOST_ALPHA 1" >> $TMPH
4592+else
4593+ echo "Unsupported CPU"
4594+ exit 1
4595+fi
4596+echo "TARGETOS=$targetos" >> config.mak
4597+if test "$noldl" = "yes" ; then
4598+ echo "CONFIG_NOLDL=yes" >> config.mak
4599+fi
4600+if test "$mingw32" = "yes" ; then
4601+ echo "CONFIG_WIN32=yes" >> config.mak
4602+ echo "#define CONFIG_WIN32 1" >> $TMPH
4603+fi
4604+if test "$cygwin" = "yes" ; then
4605+ echo "#ifndef _WIN32" >> $TMPH
4606+ echo "#define _WIN32" >> $TMPH
4607+ echo "#endif" >> $TMPH
4608+ echo "AR=ar" >> config.mak
4609+fi
4610+if test "$bigendian" = "yes" ; then
4611+ echo "WORDS_BIGENDIAN=yes" >> config.mak
4612+ echo "#define WORDS_BIGENDIAN 1" >> $TMPH
4613+fi
4614+if test "$gprof" = "yes" ; then
4615+ echo "TARGET_GPROF=yes" >> config.mak
4616+ echo "#define HAVE_GPROF 1" >> $TMPH
4617+fi
4618+if test "$build_cross" = "yes" ; then
4619+ echo "CONFIG_CROSS=yes" >> config.mak
4620+fi
4621+if test "$disable_static" = "yes" ; then
4622+ echo "DISABLE_STATIC=yes" >> config.mak
4623+fi
4624+if test "$disable_rpath" = "yes" ; then
4625+ echo "DISABLE_RPATH=yes" >> config.mak
4626+fi
4627+if test "$strip_binaries" = "yes" ; then
4628+ echo "STRIP_BINARIES=yes" >> config.mak
4629+fi
4630+if test "$use_libgcc" = "yes" ; then
4631+ echo "#define CONFIG_USE_LIBGCC" >> $TMPH
4632+ echo "CONFIG_USE_LIBGCC=yes" >> config.mak
4633+fi
4634+if test "$have_selinux" = "yes" ; then
4635+ echo "#define HAVE_SELINUX" >> $TMPH
4636+ echo "HAVE_SELINUX=yes" >> config.mak
4637+fi
4638+version=`head $source_path/VERSION`
4639+echo "VERSION=$version" >>config.mak
4640+echo "#define TCC_VERSION \"$version\"" >> $TMPH
4641+echo "@set VERSION $version" > config.texi
4642+
4643+# build tree in object directory if source path is different from current one
4644+if test "$source_path_used" = "yes" ; then
4645+ DIRS="tests"
4646+ FILES="Makefile tests/Makefile"
4647+ for dir in $DIRS ; do
4648+ mkdir -p $dir
4649+ done
4650+ for f in $FILES ; do
4651+ ln -sf $source_path/$f $f
4652+ done
4653+fi
4654+echo "SRC_PATH=$source_path" >> config.mak
4655+
4656+diff $TMPH config.h >/dev/null 2>&1
4657+if test $? -ne 0 ; then
4658+ mv -f $TMPH config.h
4659+else
4660+ echo "config.h is unchanged"
4661+fi
4662+
4663+rm -f $TMPN*
4664
4665=== removed directory '.pc/0002-Fix-a-typo-in-an-error-about-size-with-bounded-ptr.patch'
4666=== removed file '.pc/0002-Fix-a-typo-in-an-error-about-size-with-bounded-ptr.patch/i386-gen.c'
4667--- .pc/0002-Fix-a-typo-in-an-error-about-size-with-bounded-ptr.patch/i386-gen.c 2012-03-06 00:19:03 +0000
4668+++ .pc/0002-Fix-a-typo-in-an-error-about-size-with-bounded-ptr.patch/i386-gen.c 1970-01-01 00:00:00 +0000
4669@@ -1,1089 +0,0 @@
4670-/*
4671- * X86 code generator for TCC
4672- *
4673- * Copyright (c) 2001-2004 Fabrice Bellard
4674- *
4675- * This library is free software; you can redistribute it and/or
4676- * modify it under the terms of the GNU Lesser General Public
4677- * License as published by the Free Software Foundation; either
4678- * version 2 of the License, or (at your option) any later version.
4679- *
4680- * This library is distributed in the hope that it will be useful,
4681- * but WITHOUT ANY WARRANTY; without even the implied warranty of
4682- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4683- * Lesser General Public License for more details.
4684- *
4685- * You should have received a copy of the GNU Lesser General Public
4686- * License along with this library; if not, write to the Free Software
4687- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4688- */
4689-
4690-#ifdef TARGET_DEFS_ONLY
4691-
4692-/* number of available registers */
4693-#define NB_REGS 4
4694-#define NB_ASM_REGS 8
4695-
4696-/* a register can belong to several classes. The classes must be
4697- sorted from more general to more precise (see gv2() code which does
4698- assumptions on it). */
4699-#define RC_INT 0x0001 /* generic integer register */
4700-#define RC_FLOAT 0x0002 /* generic float register */
4701-#define RC_EAX 0x0004
4702-#define RC_ST0 0x0008
4703-#define RC_ECX 0x0010
4704-#define RC_EDX 0x0020
4705-#define RC_IRET RC_EAX /* function return: integer register */
4706-#define RC_LRET RC_EDX /* function return: second integer register */
4707-#define RC_FRET RC_ST0 /* function return: float register */
4708-
4709-/* pretty names for the registers */
4710-enum {
4711- TREG_EAX = 0,
4712- TREG_ECX,
4713- TREG_EDX,
4714- TREG_ST0,
4715-};
4716-
4717-/* return registers for function */
4718-#define REG_IRET TREG_EAX /* single word int return register */
4719-#define REG_LRET TREG_EDX /* second word return register (for long long) */
4720-#define REG_FRET TREG_ST0 /* float return register */
4721-
4722-/* defined if function parameters must be evaluated in reverse order */
4723-#define INVERT_FUNC_PARAMS
4724-
4725-/* defined if structures are passed as pointers. Otherwise structures
4726- are directly pushed on stack. */
4727-//#define FUNC_STRUCT_PARAM_AS_PTR
4728-
4729-/* pointer size, in bytes */
4730-#define PTR_SIZE 4
4731-
4732-/* long double size and alignment, in bytes */
4733-#define LDOUBLE_SIZE 12
4734-#define LDOUBLE_ALIGN 4
4735-/* maximum alignment (for aligned attribute support) */
4736-#define MAX_ALIGN 8
4737-
4738-
4739-#define psym oad
4740-
4741-/******************************************************/
4742-/* ELF defines */
4743-
4744-#define EM_TCC_TARGET EM_386
4745-
4746-/* relocation type for 32 bit data relocation */
4747-#define R_DATA_32 R_386_32
4748-#define R_DATA_PTR R_386_32
4749-#define R_JMP_SLOT R_386_JMP_SLOT
4750-#define R_COPY R_386_COPY
4751-
4752-#define ELF_START_ADDR 0x08048000
4753-#define ELF_PAGE_SIZE 0x1000
4754-
4755-/******************************************************/
4756-#else /* ! TARGET_DEFS_ONLY */
4757-/******************************************************/
4758-#include "tcc.h"
4759-
4760-ST_DATA const int reg_classes[NB_REGS] = {
4761- /* eax */ RC_INT | RC_EAX,
4762- /* ecx */ RC_INT | RC_ECX,
4763- /* edx */ RC_INT | RC_EDX,
4764- /* st0 */ RC_FLOAT | RC_ST0,
4765-};
4766-
4767-static unsigned long func_sub_sp_offset;
4768-static int func_ret_sub;
4769-#ifdef CONFIG_TCC_BCHECK
4770-static unsigned long func_bound_offset;
4771-#endif
4772-
4773-/* XXX: make it faster ? */
4774-ST_FUNC void g(int c)
4775-{
4776- int ind1;
4777- ind1 = ind + 1;
4778- if (ind1 > cur_text_section->data_allocated)
4779- section_realloc(cur_text_section, ind1);
4780- cur_text_section->data[ind] = c;
4781- ind = ind1;
4782-}
4783-
4784-ST_FUNC void o(unsigned int c)
4785-{
4786- while (c) {
4787- g(c);
4788- c = c >> 8;
4789- }
4790-}
4791-
4792-ST_FUNC void gen_le16(int v)
4793-{
4794- g(v);
4795- g(v >> 8);
4796-}
4797-
4798-ST_FUNC void gen_le32(int c)
4799-{
4800- g(c);
4801- g(c >> 8);
4802- g(c >> 16);
4803- g(c >> 24);
4804-}
4805-
4806-/* output a symbol and patch all calls to it */
4807-ST_FUNC void gsym_addr(int t, int a)
4808-{
4809- int n, *ptr;
4810- while (t) {
4811- ptr = (int *)(cur_text_section->data + t);
4812- n = *ptr; /* next value */
4813- *ptr = a - t - 4;
4814- t = n;
4815- }
4816-}
4817-
4818-ST_FUNC void gsym(int t)
4819-{
4820- gsym_addr(t, ind);
4821-}
4822-
4823-/* psym is used to put an instruction with a data field which is a
4824- reference to a symbol. It is in fact the same as oad ! */
4825-#define psym oad
4826-
4827-/* instruction + 4 bytes data. Return the address of the data */
4828-ST_FUNC int oad(int c, int s)
4829-{
4830- int ind1;
4831-
4832- o(c);
4833- ind1 = ind + 4;
4834- if (ind1 > cur_text_section->data_allocated)
4835- section_realloc(cur_text_section, ind1);
4836- *(int *)(cur_text_section->data + ind) = s;
4837- s = ind;
4838- ind = ind1;
4839- return s;
4840-}
4841-
4842-/* output constant with relocation if 'r & VT_SYM' is true */
4843-ST_FUNC void gen_addr32(int r, Sym *sym, int c)
4844-{
4845- if (r & VT_SYM)
4846- greloc(cur_text_section, sym, ind, R_386_32);
4847- gen_le32(c);
4848-}
4849-
4850-ST_FUNC void gen_addrpc32(int r, Sym *sym, int c)
4851-{
4852- if (r & VT_SYM)
4853- greloc(cur_text_section, sym, ind, R_386_PC32);
4854- gen_le32(c - 4);
4855-}
4856-
4857-/* generate a modrm reference. 'op_reg' contains the addtionnal 3
4858- opcode bits */
4859-static void gen_modrm(int op_reg, int r, Sym *sym, int c)
4860-{
4861- op_reg = op_reg << 3;
4862- if ((r & VT_VALMASK) == VT_CONST) {
4863- /* constant memory reference */
4864- o(0x05 | op_reg);
4865- gen_addr32(r, sym, c);
4866- } else if ((r & VT_VALMASK) == VT_LOCAL) {
4867- /* currently, we use only ebp as base */
4868- if (c == (char)c) {
4869- /* short reference */
4870- o(0x45 | op_reg);
4871- g(c);
4872- } else {
4873- oad(0x85 | op_reg, c);
4874- }
4875- } else {
4876- g(0x00 | op_reg | (r & VT_VALMASK));
4877- }
4878-}
4879-
4880-/* load 'r' from value 'sv' */
4881-ST_FUNC void load(int r, SValue *sv)
4882-{
4883- int v, t, ft, fc, fr;
4884- SValue v1;
4885-
4886-#ifdef TCC_TARGET_PE
4887- SValue v2;
4888- sv = pe_getimport(sv, &v2);
4889-#endif
4890-
4891- fr = sv->r;
4892- ft = sv->type.t;
4893- fc = sv->c.ul;
4894-
4895- v = fr & VT_VALMASK;
4896- if (fr & VT_LVAL) {
4897- if (v == VT_LLOCAL) {
4898- v1.type.t = VT_INT;
4899- v1.r = VT_LOCAL | VT_LVAL;
4900- v1.c.ul = fc;
4901- load(r, &v1);
4902- fr = r;
4903- }
4904- if ((ft & VT_BTYPE) == VT_FLOAT) {
4905- o(0xd9); /* flds */
4906- r = 0;
4907- } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
4908- o(0xdd); /* fldl */
4909- r = 0;
4910- } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
4911- o(0xdb); /* fldt */
4912- r = 5;
4913- } else if ((ft & VT_TYPE) == VT_BYTE) {
4914- o(0xbe0f); /* movsbl */
4915- } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
4916- o(0xb60f); /* movzbl */
4917- } else if ((ft & VT_TYPE) == VT_SHORT) {
4918- o(0xbf0f); /* movswl */
4919- } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
4920- o(0xb70f); /* movzwl */
4921- } else {
4922- o(0x8b); /* movl */
4923- }
4924- gen_modrm(r, fr, sv->sym, fc);
4925- } else {
4926- if (v == VT_CONST) {
4927- o(0xb8 + r); /* mov $xx, r */
4928- gen_addr32(fr, sv->sym, fc);
4929- } else if (v == VT_LOCAL) {
4930- o(0x8d); /* lea xxx(%ebp), r */
4931- gen_modrm(r, VT_LOCAL, sv->sym, fc);
4932- } else if (v == VT_CMP) {
4933- oad(0xb8 + r, 0); /* mov $0, r */
4934- o(0x0f); /* setxx %br */
4935- o(fc);
4936- o(0xc0 + r);
4937- } else if (v == VT_JMP || v == VT_JMPI) {
4938- t = v & 1;
4939- oad(0xb8 + r, t); /* mov $1, r */
4940- o(0x05eb); /* jmp after */
4941- gsym(fc);
4942- oad(0xb8 + r, t ^ 1); /* mov $0, r */
4943- } else if (v != r) {
4944- o(0x89);
4945- o(0xc0 + r + v * 8); /* mov v, r */
4946- }
4947- }
4948-}
4949-
4950-/* store register 'r' in lvalue 'v' */
4951-ST_FUNC void store(int r, SValue *v)
4952-{
4953- int fr, bt, ft, fc;
4954-
4955-#ifdef TCC_TARGET_PE
4956- SValue v2;
4957- v = pe_getimport(v, &v2);
4958-#endif
4959-
4960- ft = v->type.t;
4961- fc = v->c.ul;
4962- fr = v->r & VT_VALMASK;
4963- bt = ft & VT_BTYPE;
4964- /* XXX: incorrect if float reg to reg */
4965- if (bt == VT_FLOAT) {
4966- o(0xd9); /* fsts */
4967- r = 2;
4968- } else if (bt == VT_DOUBLE) {
4969- o(0xdd); /* fstpl */
4970- r = 2;
4971- } else if (bt == VT_LDOUBLE) {
4972- o(0xc0d9); /* fld %st(0) */
4973- o(0xdb); /* fstpt */
4974- r = 7;
4975- } else {
4976- if (bt == VT_SHORT)
4977- o(0x66);
4978- if (bt == VT_BYTE || bt == VT_BOOL)
4979- o(0x88);
4980- else
4981- o(0x89);
4982- }
4983- if (fr == VT_CONST ||
4984- fr == VT_LOCAL ||
4985- (v->r & VT_LVAL)) {
4986- gen_modrm(r, v->r, v->sym, fc);
4987- } else if (fr != r) {
4988- o(0xc0 + fr + r * 8); /* mov r, fr */
4989- }
4990-}
4991-
4992-static void gadd_sp(int val)
4993-{
4994- if (val == (char)val) {
4995- o(0xc483);
4996- g(val);
4997- } else {
4998- oad(0xc481, val); /* add $xxx, %esp */
4999- }
5000-}
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: