xref: /netbsd-src/external/bsd/elftoolchain/dist/libelf/elf_flag.c (revision 5ac3bc719ce6e70593039505b491894133237d12)
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