Branch data 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 : 176006 : 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 : 176006 : char tempsym[TEMPSYMLEN];
51 : 176006 : AsmSym_t *result;
52 : :
53 [ - + ]: 176006 : if (asmscn == NULL)
54 : : /* Something went wrong before. */
55 : : return NULL;
56 : :
57 : : /* Generate a temporary symbol if necessary. */
58 [ - + ]: 176006 : 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 : 176006 : size_t name_len = strlen (name) + 1;
75 : :
76 : 176006 : result = malloc (sizeof (AsmSym_t) + name_len);
77 [ - + ]: 176006 : if (result == NULL)
78 : : return NULL;
79 : :
80 : 176006 : rwlock_wrlock (asmscn->ctx->lock);
81 : :
82 : 176006 : result->scn = asmscn;
83 : 176006 : result->offset = asmscn->offset;
84 : 176006 : result->size = size;
85 : 176006 : result->type = type;
86 : 176006 : result->binding = binding;
87 : 176006 : result->symidx = 0;
88 : 352012 : result->strent = dwelf_strtab_add (asmscn->ctx->symbol_strtab,
89 : 176006 : memcpy (result + 1, name, name_len));
90 : :
91 [ - + ]: 176006 : 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 [ - + ]: 176006 : 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 [ - + - + ]: 176006 : else if (name != tempsym && asm_emit_symbol_p (name))
129 : : /* Only count non-private symbols. */
130 : 176006 : ++asmscn->ctx->nsymbol_tab;
131 : : }
132 : :
133 : 176006 : rwlock_unlock (asmscn->ctx->lock);
134 : :
135 : 176006 : return result;
136 : : }
|