1 /* $NetBSD: elf_flag.c,v 1.5 2024/03/03 17:37:33 christos Exp $ */
2
3 /*-
4 * Copyright (c) 2006,2008-2009,2011 Joseph Koshy
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30
31 #include <libelf.h>
32
33 #include "_libelf.h"
34
35 __RCSID("$NetBSD: elf_flag.c,v 1.5 2024/03/03 17:37:33 christos Exp $");
36
37 unsigned int
elf_flagarhdr(Elf_Arhdr * a,Elf_Cmd c,unsigned int flags)38 elf_flagarhdr(Elf_Arhdr *a, Elf_Cmd c, unsigned int flags)
39 {
40 unsigned int r;
41
42 if (a == NULL)
43 return (0);
44
45 if ((c != ELF_C_SET && c != ELF_C_CLR) ||
46 (flags & ~ELF_F_DIRTY) != 0) {
47 LIBELF_SET_ERROR(ARGUMENT, 0);
48 return (0);
49 }
50
51 if (c == ELF_C_SET)
52 r = a->ar_flags |= flags;
53 else
54 r = a->ar_flags &= ~flags;
55
56 return (r & LIBELF_F_API_MASK);
57 }
58
59 unsigned int
elf_flagdata(Elf_Data * d,Elf_Cmd c,unsigned int flags)60 elf_flagdata(Elf_Data *d, Elf_Cmd c, unsigned int flags)
61 {
62 unsigned int r;
63 struct _Libelf_Data *ld;
64
65 if (d == NULL)
66 return (0);
67
68 if ((c != ELF_C_SET && c != ELF_C_CLR) ||
69 (flags & ~ELF_F_DIRTY) != 0) {
70 LIBELF_SET_ERROR(ARGUMENT, 0);
71 return (0);
72 }
73
74 ld = (struct _Libelf_Data *) d;
75
76 if (c == ELF_C_SET)
77 r = ld->d_flags |= flags;
78 else
79 r = ld->d_flags &= ~flags;
80
81 return (r & LIBELF_F_API_MASK);
82 }
83
84 unsigned int
elf_flagehdr(Elf * e,Elf_Cmd c,unsigned int flags)85 elf_flagehdr(Elf *e, Elf_Cmd c, unsigned int flags)
86 {
87 int ec;
88 void *ehdr;
89
90 if (e == NULL)
91 return (0);
92
93 if ((c != ELF_C_SET && c != ELF_C_CLR) ||
94 (e->e_kind != ELF_K_ELF) || (flags & ~ELF_F_DIRTY) != 0 ||
95 ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
96 LIBELF_SET_ERROR(ARGUMENT, 0);
97 return (0);
98 }
99
100 if (ec == ELFCLASS32)
101 ehdr = e->e_u.e_elf.e_ehdr.e_ehdr32;
102 else
103 ehdr = e->e_u.e_elf.e_ehdr.e_ehdr64;
104
105 if (ehdr == NULL) {
106 LIBELF_SET_ERROR(SEQUENCE, 0);
107 return (0);
108 }
109
110 return (elf_flagelf(e, c, flags));
111 }
112
113 unsigned int
elf_flagelf(Elf * e,Elf_Cmd c,unsigned int flags)114 elf_flagelf(Elf *e, Elf_Cmd c, unsigned int flags)
115 {
116 unsigned int r;
117
118 if (e == NULL)
119 return (0);
120
121 if ((c != ELF_C_SET && c != ELF_C_CLR) ||
122 (e->e_kind != ELF_K_ELF) ||
123 (flags & ~(ELF_F_ARCHIVE | ELF_F_ARCHIVE_SYSV |
124 ELF_F_DIRTY | ELF_F_LAYOUT)) != 0) {
125 LIBELF_SET_ERROR(ARGUMENT, 0);
126 return (0);
127 }
128
129 if ((flags & ELF_F_ARCHIVE_SYSV) && (flags & ELF_F_ARCHIVE) == 0) {
130 LIBELF_SET_ERROR(ARGUMENT, 0);
131 return (0);
132 }
133
134 if ((flags & ELF_F_ARCHIVE) && e->e_cmd != ELF_C_WRITE) {
135 LIBELF_SET_ERROR(MODE, 0);
136 return (0);
137 }
138
139 if (c == ELF_C_SET)
140 r = e->e_flags |= flags;
141 else
142 r = e->e_flags &= ~flags;
143 return (r & LIBELF_F_API_MASK);
144 }
145
146 unsigned int
elf_flagphdr(Elf * e,Elf_Cmd c,unsigned int flags)147 elf_flagphdr(Elf *e, Elf_Cmd c, unsigned int flags)
148 {
149 int ec;
150 void *phdr;
151
152 if (e == NULL)
153 return (0);
154
155 if ((c != ELF_C_SET && c != ELF_C_CLR) ||
156 (e->e_kind != ELF_K_ELF) || (flags & ~ELF_F_DIRTY) != 0 ||
157 ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
158 LIBELF_SET_ERROR(ARGUMENT, 0);
159 return (0);
160 }
161
162 if (ec == ELFCLASS32)
163 phdr = e->e_u.e_elf.e_phdr.e_phdr32;
164 else
165 phdr = e->e_u.e_elf.e_phdr.e_phdr64;
166
167 if (phdr == NULL) {
168 LIBELF_SET_ERROR(SEQUENCE, 0);
169 return (0);
170 }
171
172 return (elf_flagelf(e, c, flags));
173 }
174
175 unsigned int
elf_flagscn(Elf_Scn * s,Elf_Cmd c,unsigned int flags)176 elf_flagscn(Elf_Scn *s, Elf_Cmd c, unsigned int flags)
177 {
178 unsigned int r;
179
180 if (s == NULL)
181 return (0);
182
183 if ((c != ELF_C_SET && c != ELF_C_CLR) ||
184 (flags & ~ELF_F_DIRTY) != 0) {
185 LIBELF_SET_ERROR(ARGUMENT, 0);
186 return (0);
187 }
188
189 if (c == ELF_C_SET)
190 r = s->s_flags |= flags;
191 else
192 r = s->s_flags &= ~flags;
193 return (r & LIBELF_F_API_MASK);
194 }
195
196 unsigned int
elf_flagshdr(Elf_Scn * s,Elf_Cmd c,unsigned int flags)197 elf_flagshdr(Elf_Scn *s, Elf_Cmd c, unsigned int flags)
198 {
199 return (elf_flagscn(s, c, flags));
200 }
201