Line data Source code
1 : /* Define new symbol for current position in given section.
2 : Copyright (C) 2002, 2005, 2016 Red Hat, Inc.
3 : This file is part of elfutils.
4 : Written by Ulrich Drepper <drepper@redhat.com>, 2002.
5 :
6 : This file is free software; you can redistribute it and/or modify
7 : it under the terms of either
8 :
9 : * the GNU Lesser General Public License as published by the Free
10 : Software Foundation; either version 3 of the License, or (at
11 : your option) any later version
12 :
13 : or
14 :
15 : * the GNU General Public License as published by the Free
16 : Software Foundation; either version 2 of the License, or (at
17 : your option) any later version
18 :
19 : or both in parallel, as here.
20 :
21 : elfutils is distributed in the hope that it will be useful, but
22 : WITHOUT ANY WARRANTY; without even the implied warranty of
23 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 : General Public License for more details.
25 :
26 : You should have received copies of the GNU General Public License and
27 : the GNU Lesser General Public License along with this program. If
28 : not, see <http://www.gnu.org/licenses/>. */
29 :
30 : #ifdef HAVE_CONFIG_H
31 : # include <config.h>
32 : #endif
33 :
34 : #include <inttypes.h>
35 : #include <stdio.h>
36 : #include <stdlib.h>
37 : #include <string.h>
38 :
39 : #include <libasmP.h>
40 : #include <system.h>
41 :
42 :
43 : AsmSym_t *
44 88003 : asm_newsym (AsmScn_t *asmscn, const char *name, GElf_Xword size,
45 : int type, int binding)
46 : {
47 : #define TEMPSYMLEN 10
48 : char tempsym[TEMPSYMLEN];
49 : AsmSym_t *result;
50 :
51 88003 : if (asmscn == NULL)
52 : /* Something went wrong before. */
53 : return NULL;
54 :
55 : /* Generate a temporary symbol if necessary. */
56 88003 : if (name == NULL)
57 : {
58 : /* If a local symbol name is created the symbol better have
59 : local binding. */
60 0 : if (binding != STB_LOCAL)
61 : {
62 0 : __libasm_seterrno (ASM_E_INVALID);
63 0 : return NULL;
64 : }
65 :
66 : // XXX This requires getting the format from the machine backend. */
67 0 : snprintf (tempsym, TEMPSYMLEN, ".L%07u", asmscn->ctx->tempsym_count++);
68 :
69 0 : name = tempsym;
70 : }
71 :
72 88003 : size_t name_len = strlen (name) + 1;
73 :
74 88003 : result = (AsmSym_t *) malloc (sizeof (AsmSym_t) + name_len);
75 88003 : if (result == NULL)
76 : return NULL;
77 :
78 88003 : rwlock_wrlock (asmscn->ctx->lock);
79 :
80 88003 : result->scn = asmscn;
81 88003 : result->offset = asmscn->offset;
82 88003 : result->size = size;
83 88003 : result->type = type;
84 88003 : result->binding = binding;
85 88003 : result->symidx = 0;
86 88003 : result->strent = dwelf_strtab_add (asmscn->ctx->symbol_strtab,
87 88003 : memcpy (result + 1, name, name_len));
88 :
89 88003 : if (unlikely (asmscn->ctx->textp))
90 : {
91 : /* We are only interested in the name and don't need to know whether
92 : it is a local name or not. */
93 : /* First print the binding pseudo-op. */
94 0 : if (binding == STB_GLOBAL)
95 0 : fprintf (asmscn->ctx->out.file, "\t.globl\t%s\n", name);
96 0 : else if (binding == STB_WEAK)
97 0 : fprintf (asmscn->ctx->out.file, "\t.weak\t%s\n", name);
98 :
99 : /* Next the symbol type. */
100 0 : if (type == STT_OBJECT)
101 0 : fprintf (asmscn->ctx->out.file, "\t.type\t%s,@object\n", name);
102 0 : else if (type == STT_FUNC)
103 0 : fprintf (asmscn->ctx->out.file, "\t.type\t%s,@function\n", name);
104 :
105 : /* Finally the size and the label. */
106 0 : fprintf (asmscn->ctx->out.file, "\t.size\t%s,%" PRIuMAX "\n%s:\n",
107 : name, (uintmax_t) size, name);
108 : }
109 : else
110 : {
111 : /* Put the symbol in the hash table so that we can later find it. */
112 88003 : if (asm_symbol_tab_insert (&asmscn->ctx->symbol_tab, elf_hash (name),
113 : result) != 0)
114 : {
115 : /* The symbol already exists. */
116 0 : __libasm_seterrno (ASM_E_DUPLSYM);
117 : /* Note that we can free the entry since there must be no
118 : reference in the string table to the string. We can only
119 : fail to insert the symbol into the symbol table if there
120 : is already a symbol with this name. In this case the
121 : dwelf_strtab_add function would use the previously provided
122 : name. */
123 0 : free (result);
124 0 : result = NULL;
125 : }
126 88003 : else if (name != tempsym && asm_emit_symbol_p (name))
127 : /* Only count non-private symbols. */
128 88003 : ++asmscn->ctx->nsymbol_tab;
129 : }
130 :
131 : rwlock_unlock (asmscn->ctx->lock);
132 :
133 88003 : return result;
134 : }
|