Line data Source code
1 : /* Define new symbol for current position in given section.
2 : Copyright (C) 2002, 2005, 2016, 2017 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 : /* We don't really expect labels with many digits, but in theory it could
48 : be 10 digits (plus ".L" and a zero terminator). */
49 : #define TEMPSYMLEN 13
50 : char tempsym[TEMPSYMLEN];
51 : AsmSym_t *result;
52 :
53 88003 : if (asmscn == NULL)
54 : /* Something went wrong before. */
55 : return NULL;
56 :
57 : /* Generate a temporary symbol if necessary. */
58 88003 : if (name == NULL)
59 : {
60 : /* If a local symbol name is created the symbol better have
61 : local binding. */
62 0 : if (binding != STB_LOCAL)
63 : {
64 0 : __libasm_seterrno (ASM_E_INVALID);
65 0 : return NULL;
66 : }
67 :
68 : // XXX This requires getting the format from the machine backend. */
69 0 : snprintf (tempsym, TEMPSYMLEN, ".L%07u", asmscn->ctx->tempsym_count++);
70 :
71 0 : name = tempsym;
72 : }
73 :
74 88003 : size_t name_len = strlen (name) + 1;
75 :
76 88003 : result = (AsmSym_t *) malloc (sizeof (AsmSym_t) + name_len);
77 88003 : if (result == NULL)
78 : return NULL;
79 :
80 88003 : rwlock_wrlock (asmscn->ctx->lock);
81 :
82 88003 : result->scn = asmscn;
83 88003 : result->offset = asmscn->offset;
84 88003 : result->size = size;
85 88003 : result->type = type;
86 88003 : result->binding = binding;
87 88003 : result->symidx = 0;
88 88003 : result->strent = dwelf_strtab_add (asmscn->ctx->symbol_strtab,
89 176006 : memcpy (result + 1, name, name_len));
90 :
91 88003 : if (unlikely (asmscn->ctx->textp))
92 : {
93 : /* We are only interested in the name and don't need to know whether
94 : it is a local name or not. */
95 : /* First print the binding pseudo-op. */
96 0 : if (binding == STB_GLOBAL)
97 0 : fprintf (asmscn->ctx->out.file, "\t.globl\t%s\n", name);
98 0 : else if (binding == STB_WEAK)
99 0 : fprintf (asmscn->ctx->out.file, "\t.weak\t%s\n", name);
100 :
101 : /* Next the symbol type. */
102 0 : if (type == STT_OBJECT)
103 0 : fprintf (asmscn->ctx->out.file, "\t.type\t%s,@object\n", name);
104 0 : else if (type == STT_FUNC)
105 0 : fprintf (asmscn->ctx->out.file, "\t.type\t%s,@function\n", name);
106 :
107 : /* Finally the size and the label. */
108 0 : fprintf (asmscn->ctx->out.file, "\t.size\t%s,%" PRIuMAX "\n%s:\n",
109 : name, (uintmax_t) size, name);
110 : }
111 : else
112 : {
113 : /* Put the symbol in the hash table so that we can later find it. */
114 88003 : if (asm_symbol_tab_insert (&asmscn->ctx->symbol_tab, elf_hash (name),
115 : result) != 0)
116 : {
117 : /* The symbol already exists. */
118 0 : __libasm_seterrno (ASM_E_DUPLSYM);
119 : /* Note that we can free the entry since there must be no
120 : reference in the string table to the string. We can only
121 : fail to insert the symbol into the symbol table if there
122 : is already a symbol with this name. In this case the
123 : dwelf_strtab_add function would use the previously provided
124 : name. */
125 0 : free (result);
126 0 : result = NULL;
127 : }
128 88003 : else if (name != tempsym && asm_emit_symbol_p (name))
129 : /* Only count non-private symbols. */
130 88003 : ++asmscn->ctx->nsymbol_tab;
131 : }
132 :
133 : rwlock_unlock (asmscn->ctx->lock);
134 :
135 88003 : return result;
136 : }
|