c2f1971a2e22cb27d9c5f7fcddb75c76002aae7b
[platform/upstream/elfutils.git] / src / ldscript.y
1 %{
2 /* Parser for linker scripts.
3    Copyright (C) 2001-2011 Red Hat, Inc.
4    This file is part of Red Hat elfutils.
5    Written by Ulrich Drepper <drepper@redhat.com>, 2001.
6
7    Red Hat elfutils is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by the
9    Free Software Foundation; version 2 of the License.
10
11    Red Hat elfutils is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    General Public License for more details.
15
16    You should have received a copy of the GNU General Public License along
17    with Red Hat elfutils; if not, write to the Free Software Foundation,
18    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
19
20    Red Hat elfutils is an included package of the Open Invention Network.
21    An included package of the Open Invention Network is a package for which
22    Open Invention Network licensees cross-license their patents.  No patent
23    license is granted, either expressly or impliedly, by designation as an
24    included package.  Should you wish to participate in the Open Invention
25    Network licensing program, please visit www.openinventionnetwork.com
26    <http://www.openinventionnetwork.com>.  */
27
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
31
32 #include <assert.h>
33 #include <error.h>
34 #include <libintl.h>
35 #include <stdbool.h>
36 #include <stdint.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include <system.h>
42 #include <ld.h>
43
44 /* The error handler.  */
45 static void yyerror (const char *s);
46
47 /* Some helper functions we need to construct the data structures
48    describing information from the file.  */
49 static struct expression *new_expr (int tag);
50 static struct input_section_name *new_input_section_name (const char *name,
51                                                           bool sort_flag);
52 static struct input_rule *new_input_rule (int tag);
53 static struct output_rule *new_output_rule (int tag);
54 static struct assignment *new_assignment (const char *variable,
55                                           struct expression *expression,
56                                           bool provide_flag);
57 static void new_segment (int mode, struct output_rule *output_rule);
58 static struct filename_list *new_filename_listelem (const char *string);
59 static void add_inputfiles (struct filename_list *fnames);
60 static struct id_list *new_id_listelem (const char *str);
61  static struct filename_list *mark_as_needed (struct filename_list *listp);
62 static struct version *new_version (struct id_list *local,
63                                     struct id_list *global);
64 static struct version *merge_versions (struct version *one,
65                                        struct version *two);
66 static void add_versions (struct version *versions);
67
68 extern int yylex (void);
69 %}
70
71 %union {
72   uintmax_t num;
73   enum expression_tag op;
74   char *str;
75   struct expression *expr;
76   struct input_section_name *sectionname;
77   struct filemask_section_name *filemask_section_name;
78   struct input_rule *input_rule;
79   struct output_rule *output_rule;
80   struct assignment *assignment;
81   struct filename_list *filename_list;
82   struct version *version;
83   struct id_list *id_list;
84 }
85
86 %token kADD_OP
87 %token kALIGN
88 %token kAS_NEEDED
89 %token kENTRY
90 %token kEXCLUDE_FILE
91 %token <str> kFILENAME
92 %token kGLOBAL
93 %token kGROUP
94 %token <str> kID
95 %token kINPUT
96 %token kINTERP
97 %token kKEEP
98 %token kLOCAL
99 %token <num> kMODE
100 %token kMUL_OP
101 %token <num> kNUM
102 %token kOUTPUT_FORMAT
103 %token kPAGESIZE
104 %token kPROVIDE
105 %token kSEARCH_DIR
106 %token kSEGMENT
107 %token kSIZEOF_HEADERS
108 %token kSORT
109 %token kVERSION
110 %token kVERSION_SCRIPT
111
112 %left '|'
113 %left '&'
114 %left ADD_OP
115 %left MUL_OP '*'
116
117 %type <op> kADD_OP
118 %type <op> kMUL_OP
119 %type <str> filename_id
120 %type <str> filename_id_star
121 %type <str> exclude_opt
122 %type <expr> expr
123 %type <sectionname> sort_opt_name
124 %type <filemask_section_name> sectionname
125 %type <input_rule> inputsection
126 %type <input_rule> inputsections
127 %type <output_rule> outputsection
128 %type <output_rule> outputsections
129 %type <assignment> assignment
130 %type <filename_list> filename_id_list
131 %type <filename_list> filename_id_listelem
132 %type <version> versionlist
133 %type <version> version
134 %type <version> version_stmt_list
135 %type <version> version_stmt
136 %type <id_list> filename_id_star_list
137
138 %expect 16
139
140 %%
141
142 script_or_version:
143                   file
144                 | kVERSION_SCRIPT versionlist
145                     { add_versions ($2); }
146                 ;
147
148 file:             file content
149                 | content
150                 ;
151
152 content:          kENTRY '(' kID ')' ';'
153                     {
154                       if (likely (ld_state.entry == NULL))
155                         ld_state.entry = $3;
156                     }
157                 | kSEARCH_DIR '(' filename_id ')' ';'
158                     {
159                       ld_new_searchdir ($3);
160                     }
161                 | kPAGESIZE '(' kNUM ')' ';'
162                     {
163                       if (likely (ld_state.pagesize == 0))
164                         ld_state.pagesize = $3;
165                     }
166                 | kINTERP '(' filename_id ')' ';'
167                     {
168                       if (likely (ld_state.interp == NULL)
169                           && ld_state.file_type != dso_file_type)
170                         ld_state.interp = $3;
171                     }
172                 | kSEGMENT kMODE '{' outputsections '}'
173                     {
174                       new_segment ($2, $4);
175                     }
176                 | kSEGMENT error '{' outputsections '}'
177                     {
178                       fputs_unlocked (gettext ("mode for segment invalid\n"),
179                                       stderr);
180                       new_segment (0, $4);
181                     }
182                 | kGROUP '(' filename_id_list ')'
183                     {
184                       /* First little optimization.  If there is only one
185                          file in the group don't do anything.  */
186                       if ($3 != $3->next)
187                         {
188                           $3->next->group_start = 1;
189                           $3->group_end = 1;
190                         }
191                       add_inputfiles ($3);
192                     }
193                 | kINPUT '(' filename_id_list ')'
194                     { add_inputfiles ($3); }
195                 | kAS_NEEDED '(' filename_id_list ')'
196                     { add_inputfiles (mark_as_needed ($3)); }
197                 | kVERSION '{' versionlist '}'
198                     { add_versions ($3); }
199                 | kOUTPUT_FORMAT '(' filename_id ')'
200                     { /* XXX TODO */ }
201                 ;
202
203 outputsections:   outputsections outputsection
204                     {
205                       $2->next = $1->next;
206                       $$ = $1->next = $2;
207                     }
208                 | outputsection
209                     { $$ = $1; }
210                 ;
211
212 outputsection:    assignment ';'
213                     {
214                       $$ = new_output_rule (output_assignment);
215                       $$->val.assignment = $1;
216                     }
217                 | kID '{' inputsections '}'
218                     {
219                       $$ = new_output_rule (output_section);
220                       $$->val.section.name = $1;
221                       $$->val.section.input = $3->next;
222                       if (ld_state.strip == strip_debug
223                           && ebl_debugscn_p (ld_state.ebl, $1))
224                         $$->val.section.ignored = true;
225                       else
226                         $$->val.section.ignored = false;
227                       $3->next = NULL;
228                     }
229                 | kID ';'
230                     {
231                       /* This is a short cut for "ID { *(ID) }".  */
232                       $$ = new_output_rule (output_section);
233                       $$->val.section.name = $1;
234                       $$->val.section.input = new_input_rule (input_section);
235                       $$->val.section.input->next = NULL;
236                       $$->val.section.input->val.section =
237                         (struct filemask_section_name *)
238                           obstack_alloc (&ld_state.smem,
239                                          sizeof (struct filemask_section_name));
240                       $$->val.section.input->val.section->filemask = NULL;
241                       $$->val.section.input->val.section->excludemask = NULL;
242                       $$->val.section.input->val.section->section_name =
243                         new_input_section_name ($1, false);
244                       $$->val.section.input->val.section->keep_flag = false;
245                       if (ld_state.strip == strip_debug
246                           && ebl_debugscn_p (ld_state.ebl, $1))
247                         $$->val.section.ignored = true;
248                       else
249                         $$->val.section.ignored = false;
250                     }
251                 ;
252
253 assignment:       kID '=' expr
254                     { $$ = new_assignment ($1, $3, false); }
255                 | kPROVIDE '(' kID '=' expr ')'
256                     { $$ = new_assignment ($3, $5, true); }
257                 ;
258
259 inputsections:    inputsections inputsection
260                     {
261                       $2->next = $1->next;
262                       $$ = $1->next = $2;
263                     }
264                 | inputsection
265                     { $$ = $1; }
266                 ;
267
268 inputsection:     sectionname
269                     {
270                       $$ = new_input_rule (input_section);
271                       $$->val.section = $1;
272                     }
273                 | kKEEP '(' sectionname ')'
274                     {
275                       $3->keep_flag = true;
276
277                       $$ = new_input_rule (input_section);
278                       $$->val.section = $3;
279                     }
280                 | assignment ';'
281                     {
282                       $$ = new_input_rule (input_assignment);
283                       $$->val.assignment = $1;
284                     }
285                 ;
286
287 sectionname:      filename_id_star '(' exclude_opt sort_opt_name ')'
288                     {
289                       $$ = (struct filemask_section_name *)
290                         obstack_alloc (&ld_state.smem, sizeof (*$$));
291                       $$->filemask = $1;
292                       $$->excludemask = $3;
293                       $$->section_name = $4;
294                       $$->keep_flag = false;
295                     }
296                 ;
297
298 sort_opt_name:    kID
299                     { $$ = new_input_section_name ($1, false); }
300                 | kSORT '(' kID ')'
301                     { $$ = new_input_section_name ($3, true); }
302                 ;
303
304 exclude_opt:      kEXCLUDE_FILE '(' filename_id ')'
305                     { $$ = $3; }
306                 |
307                     { $$ = NULL; }
308                 ;
309
310 expr:             kALIGN '(' expr ')'
311                     {
312                       $$ = new_expr (exp_align);
313                       $$->val.child = $3;
314                     }
315                 | '(' expr ')'
316                     { $$ = $2; }
317                 | expr '*' expr
318                     {
319                       $$ = new_expr (exp_mult);
320                       $$->val.binary.left = $1;
321                       $$->val.binary.right = $3;
322                     }
323                 | expr kMUL_OP expr
324                     {
325                       $$ = new_expr ($2);
326                       $$->val.binary.left = $1;
327                       $$->val.binary.right = $3;
328                     }
329                 | expr kADD_OP expr
330                     {
331                       $$ = new_expr ($2);
332                       $$->val.binary.left = $1;
333                       $$->val.binary.right = $3;
334                     }
335                 | expr '&' expr
336                     {
337                       $$ = new_expr (exp_and);
338                       $$->val.binary.left = $1;
339                       $$->val.binary.right = $3;
340                     }
341                 | expr '|' expr
342                     {
343                       $$ = new_expr (exp_or);
344                       $$->val.binary.left = $1;
345                       $$->val.binary.right = $3;
346                     }
347                 | kNUM
348                     {
349                       $$ = new_expr (exp_num);
350                       $$->val.num = $1;
351                     }
352                 | kID
353                     {
354                       $$ = new_expr (exp_id);
355                       $$->val.str = $1;
356                     }
357                 | kSIZEOF_HEADERS
358                     { $$ = new_expr (exp_sizeof_headers); }
359                 | kPAGESIZE
360                     { $$ = new_expr (exp_pagesize); }
361                 ;
362
363 filename_id_list: filename_id_list comma_opt filename_id_listelem
364                     {
365                       $3->next = $1->next;
366                       $$ = $1->next = $3;
367                     }
368                 | filename_id_listelem
369                     { $$ = $1; }
370                 ;
371
372 comma_opt:        ','
373                 |
374                 ;
375
376 filename_id_listelem: kGROUP '(' filename_id_list ')'
377                     {
378                       /* First little optimization.  If there is only one
379                          file in the group don't do anything.  */
380                       if ($3 != $3->next)
381                         {
382                           $3->next->group_start = 1;
383                           $3->group_end = 1;
384                         }
385                       $$ = $3;
386                     }
387                 | kAS_NEEDED '(' filename_id_list ')'
388                     { $$ = mark_as_needed ($3); }
389                 | filename_id
390                     { $$ = new_filename_listelem ($1); }
391                 ;
392
393
394 versionlist:      versionlist version
395                     {
396                       $2->next = $1->next;
397                       $$ = $1->next = $2;
398                     }
399                 | version
400                     { $$ = $1; }
401                 ;
402
403 version:          '{' version_stmt_list '}' ';'
404                     {
405                       $2->versionname = "";
406                       $2->parentname = NULL;
407                       $$ = $2;
408                     }
409                 | filename_id '{' version_stmt_list '}' ';'
410                     {
411                       $3->versionname = $1;
412                       $3->parentname = NULL;
413                       $$ = $3;
414                     }
415                 | filename_id '{' version_stmt_list '}' filename_id ';'
416                     {
417                       $3->versionname = $1;
418                       $3->parentname = $5;
419                       $$ = $3;
420                     }
421                 ;
422
423 version_stmt_list:
424                   version_stmt_list version_stmt
425                     { $$ = merge_versions ($1, $2); }
426                 | version_stmt
427                     { $$ = $1; }
428                 ;
429
430 version_stmt:     kGLOBAL filename_id_star_list
431                     { $$ = new_version (NULL, $2); }
432                 | kLOCAL filename_id_star_list
433                     { $$ = new_version ($2, NULL); }
434                 ;
435
436 filename_id_star_list:
437                   filename_id_star_list filename_id_star ';'
438                     {
439                       struct id_list *newp = new_id_listelem ($2);
440                       newp->next = $1->next;
441                       $$ = $1->next = newp;
442                     }
443                 | filename_id_star ';'
444                     { $$ = new_id_listelem ($1); }
445                 ;
446
447 filename_id:      kFILENAME
448                     { $$ = $1; }
449                 | kID
450                     { $$ = $1; }
451                 ;
452
453 filename_id_star: filename_id
454                     { $$ = $1; }
455                 | '*'
456                     { $$ = NULL; }
457                 ;
458
459 %%
460
461 static void
462 yyerror (const char *s)
463 {
464   error (0, 0, (ld_scan_version_script
465                 ? gettext ("while reading version script '%s': %s at line %d")
466                 : gettext ("while reading linker script '%s': %s at line %d")),
467          ldin_fname, gettext (s), ldlineno);
468 }
469
470
471 static struct expression *
472 new_expr (int tag)
473 {
474   struct expression *newp = (struct expression *)
475     obstack_alloc (&ld_state.smem, sizeof (*newp));
476
477   newp->tag = tag;
478   return newp;
479 }
480
481
482 static struct input_section_name *
483 new_input_section_name (const char *name, bool sort_flag)
484 {
485   struct input_section_name *newp = (struct input_section_name *)
486     obstack_alloc (&ld_state.smem, sizeof (*newp));
487
488   newp->name = name;
489   newp->sort_flag = sort_flag;
490   return newp;
491 }
492
493
494 static struct input_rule *
495 new_input_rule (int tag)
496 {
497   struct input_rule *newp = (struct input_rule *)
498     obstack_alloc (&ld_state.smem, sizeof (*newp));
499
500   newp->tag = tag;
501   newp->next = newp;
502   return newp;
503 }
504
505
506 static struct output_rule *
507 new_output_rule (int tag)
508 {
509   struct output_rule *newp = (struct output_rule *)
510     memset (obstack_alloc (&ld_state.smem, sizeof (*newp)),
511             '\0', sizeof (*newp));
512
513   newp->tag = tag;
514   newp->next = newp;
515   return newp;
516 }
517
518
519 static struct assignment *
520 new_assignment (const char *variable, struct expression *expression,
521                 bool provide_flag)
522 {
523   struct assignment *newp = (struct assignment *)
524     obstack_alloc (&ld_state.smem, sizeof (*newp));
525
526   newp->variable = variable;
527   newp->expression = expression;
528   newp->sym = NULL;
529   newp->provide_flag = provide_flag;
530
531   /* Insert the symbol into a hash table.  We will later have to matc*/
532   return newp;
533 }
534
535
536 static void
537 new_segment (int mode, struct output_rule *output_rule)
538 {
539   struct output_segment *newp;
540
541   newp
542     = (struct output_segment *) obstack_alloc (&ld_state.smem, sizeof (*newp));
543   newp->mode = mode;
544   newp->next = newp;
545
546   newp->output_rules = output_rule->next;
547   output_rule->next = NULL;
548
549   /* Enqueue the output segment description.  */
550   if (ld_state.output_segments == NULL)
551     ld_state.output_segments = newp;
552   else
553     {
554       newp->next = ld_state.output_segments->next;
555       ld_state.output_segments = ld_state.output_segments->next = newp;
556     }
557
558   /* If the output file should be stripped of all symbol set the flag
559      in the structures of all output sections.  */
560   if (mode == 0 && ld_state.strip == strip_all)
561     {
562       struct output_rule *runp;
563
564       for (runp = newp->output_rules; runp != NULL; runp = runp->next)
565         if (runp->tag == output_section)
566           runp->val.section.ignored = true;
567     }
568 }
569
570
571 static struct filename_list *
572 new_filename_listelem (const char *string)
573 {
574   struct filename_list *newp;
575
576   /* We use calloc and not the obstack since this object can be freed soon.  */
577   newp = (struct filename_list *) xcalloc (1, sizeof (*newp));
578   newp->name = string;
579   newp->next = newp;
580   return newp;
581 }
582
583
584 static struct filename_list *
585 mark_as_needed (struct filename_list *listp)
586 {
587   struct filename_list *runp = listp;
588   do
589     {
590       runp->as_needed = true;
591       runp = runp->next;
592     }
593   while (runp != listp);
594
595   return listp;
596 }
597
598
599 static void
600 add_inputfiles (struct filename_list *fnames)
601 {
602   assert (fnames != NULL);
603
604   if (ld_state.srcfiles == NULL)
605     ld_state.srcfiles = fnames;
606   else
607     {
608       struct filename_list *first = ld_state.srcfiles->next;
609
610       ld_state.srcfiles->next = fnames->next;
611       fnames->next = first;
612       ld_state.srcfiles->next = fnames;
613     }
614 }
615
616
617 static _Bool
618 special_char_p (const char *str)
619 {
620   while (*str != '\0')
621     {
622       if (__builtin_expect (*str == '*', 0)
623           || __builtin_expect (*str == '?', 0)
624           || __builtin_expect (*str == '[', 0))
625         return true;
626
627       ++str;
628     }
629
630   return false;
631 }
632
633
634 static struct id_list *
635 new_id_listelem (const char *str)
636 {
637   struct id_list *newp;
638
639   newp = (struct id_list *) obstack_alloc (&ld_state.smem, sizeof (*newp));
640   if (str == NULL)
641     newp->u.id_type = id_all;
642   else if (__builtin_expect (special_char_p (str), false))
643     newp->u.id_type = id_wild;
644   else
645     newp->u.id_type = id_str;
646   newp->id = str;
647   newp->next = newp;
648
649   return newp;
650 }
651
652
653 static struct version *
654 new_version (struct id_list *local, struct id_list *global)
655 {
656   struct version *newp;
657
658   newp = (struct version *) obstack_alloc (&ld_state.smem, sizeof (*newp));
659   newp->next = newp;
660   newp->local_names = local;
661   newp->global_names = global;
662   newp->versionname = NULL;
663   newp->parentname = NULL;
664
665   return newp;
666 }
667
668
669 static struct version *
670 merge_versions (struct version *one, struct version *two)
671 {
672   assert (two->local_names == NULL || two->global_names == NULL);
673
674   if (two->local_names != NULL)
675     {
676       if (one->local_names == NULL)
677         one->local_names = two->local_names;
678       else
679         {
680           two->local_names->next = one->local_names->next;
681           one->local_names = one->local_names->next = two->local_names;
682         }
683     }
684   else
685     {
686       if (one->global_names == NULL)
687         one->global_names = two->global_names;
688       else
689         {
690           two->global_names->next = one->global_names->next;
691           one->global_names = one->global_names->next = two->global_names;
692         }
693     }
694
695   return one;
696 }
697
698
699 static void
700 add_id_list (const char *versionname, struct id_list *runp, _Bool local)
701 {
702   struct id_list *lastp = runp;
703
704   if (runp == NULL)
705     /* Nothing to do.  */
706     return;
707
708   /* Convert into a simple single-linked list.  */
709   runp = runp->next;
710   assert (runp != NULL);
711   lastp->next = NULL;
712
713   do
714     if (runp->u.id_type == id_str)
715       {
716         struct id_list *curp;
717         struct id_list *defp;
718         unsigned long int hval = elf_hash (runp->id);
719
720         curp = runp;
721         runp = runp->next;
722
723         defp = ld_version_str_tab_find (&ld_state.version_str_tab, hval, curp);
724         if (defp != NULL)
725           {
726             /* There is already a version definition for this symbol.  */
727             while (strcmp (defp->u.s.versionname, versionname) != 0)
728               {
729                 if (defp->next == NULL)
730                   {
731                     /* No version like this so far.  */
732                     defp->next = curp;
733                     curp->u.s.local = local;
734                     curp->u.s.versionname = versionname;
735                     curp->next = NULL;
736                     defp = NULL;
737                     break;
738                   }
739
740                 defp = defp->next;
741               }
742
743             if (defp != NULL && defp->u.s.local != local)
744               error (EXIT_FAILURE, 0, versionname[0] == '\0'
745                      ? gettext ("\
746 symbol '%s' is declared both local and global for unnamed version")
747                      : gettext ("\
748 symbol '%s' is declared both local and global for version '%s'"),
749                      runp->id, versionname);
750           }
751         else
752           {
753             /* This is the first version definition for this symbol.  */
754             ld_version_str_tab_insert (&ld_state.version_str_tab, hval, curp);
755
756             curp->u.s.local = local;
757             curp->u.s.versionname = versionname;
758             curp->next = NULL;
759           }
760       }
761     else if (runp->u.id_type == id_all)
762       {
763         if (local)
764           {
765             if (ld_state.default_bind_global)
766               error (EXIT_FAILURE, 0,
767                      gettext ("default visibility set as local and global"));
768             ld_state.default_bind_local = true;
769           }
770         else
771           {
772             if (ld_state.default_bind_local)
773               error (EXIT_FAILURE, 0,
774                      gettext ("default visibility set as local and global"));
775             ld_state.default_bind_global = true;
776           }
777
778         runp = runp->next;
779       }
780     else
781       {
782         assert (runp->u.id_type == id_wild);
783         /* XXX TBI */
784         abort ();
785       }
786   while (runp != NULL);
787 }
788
789
790 static void
791 add_versions (struct version *versions)
792 {
793   struct version *lastp = versions;
794
795   if (versions == NULL)
796     return;
797
798   /* Convert into a simple single-linked list.  */
799   versions = versions->next;
800   assert (versions != NULL);
801   lastp->next = NULL;
802
803   do
804     {
805       add_id_list (versions->versionname, versions->local_names, true);
806       add_id_list (versions->versionname, versions->global_names, false);
807
808       versions = versions->next;
809     }
810   while (versions != NULL);
811 }