1*839529caSEd Maste /*-
2*839529caSEd Maste  * Copyright (c) 2016 Kai Wang
3*839529caSEd Maste  * All rights reserved.
4*839529caSEd Maste  *
5*839529caSEd Maste  * Redistribution and use in source and binary forms, with or without
6*839529caSEd Maste  * modification, are permitted provided that the following conditions
7*839529caSEd Maste  * are met:
8*839529caSEd Maste  * 1. Redistributions of source code must retain the above copyright
9*839529caSEd Maste  *    notice, this list of conditions and the following disclaimer.
10*839529caSEd Maste  * 2. Redistributions in binary form must reproduce the above copyright
11*839529caSEd Maste  *    notice, this list of conditions and the following disclaimer in the
12*839529caSEd Maste  *    documentation and/or other materials provided with the distribution.
13*839529caSEd Maste  *
14*839529caSEd Maste  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*839529caSEd Maste  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*839529caSEd Maste  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*839529caSEd Maste  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*839529caSEd Maste  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*839529caSEd Maste  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*839529caSEd Maste  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*839529caSEd Maste  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*839529caSEd Maste  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*839529caSEd Maste  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*839529caSEd Maste  * SUCH DAMAGE.
25*839529caSEd Maste  */
26*839529caSEd Maste 
27*839529caSEd Maste #include <sys/param.h>
28*839529caSEd Maste #include <assert.h>
29*839529caSEd Maste #include <errno.h>
30*839529caSEd Maste #include <stdlib.h>
31*839529caSEd Maste #include <unistd.h>
32*839529caSEd Maste 
33*839529caSEd Maste #include "_libpe.h"
34*839529caSEd Maste 
35*839529caSEd Maste ELFTC_VCSID("$Id: libpe_buffer.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
36*839529caSEd Maste 
37*839529caSEd Maste PE_SecBuf *
libpe_alloc_buffer(PE_Scn * ps,size_t sz)38*839529caSEd Maste libpe_alloc_buffer(PE_Scn *ps, size_t sz)
39*839529caSEd Maste {
40*839529caSEd Maste 	PE_SecBuf *sb;
41*839529caSEd Maste 
42*839529caSEd Maste 	if ((sb = malloc(sizeof(PE_SecBuf))) == NULL) {
43*839529caSEd Maste 		errno = ENOMEM;
44*839529caSEd Maste 		return (NULL);
45*839529caSEd Maste 	}
46*839529caSEd Maste 
47*839529caSEd Maste 	sb->sb_ps = ps;
48*839529caSEd Maste 	sb->sb_flags = 0;
49*839529caSEd Maste 	sb->sb_pb.pb_align = 1;
50*839529caSEd Maste 	sb->sb_pb.pb_off = 0;
51*839529caSEd Maste 	sb->sb_pb.pb_size = sz;
52*839529caSEd Maste 	if (sz > 0) {
53*839529caSEd Maste 		if ((sb->sb_pb.pb_buf = malloc(sz)) == NULL) {
54*839529caSEd Maste 			free(sb);
55*839529caSEd Maste 			errno = ENOMEM;
56*839529caSEd Maste 			return (NULL);
57*839529caSEd Maste 		}
58*839529caSEd Maste 		sb->sb_flags |= LIBPE_F_BUFFER_MALLOCED;
59*839529caSEd Maste 	} else
60*839529caSEd Maste 		sb->sb_pb.pb_buf = NULL;
61*839529caSEd Maste 
62*839529caSEd Maste 	STAILQ_INSERT_TAIL(&ps->ps_b, sb, sb_next);
63*839529caSEd Maste 
64*839529caSEd Maste 	return (sb);
65*839529caSEd Maste }
66*839529caSEd Maste 
67*839529caSEd Maste void
libpe_release_buffer(PE_SecBuf * sb)68*839529caSEd Maste libpe_release_buffer(PE_SecBuf *sb)
69*839529caSEd Maste {
70*839529caSEd Maste 	PE_Scn *ps;
71*839529caSEd Maste 
72*839529caSEd Maste 	assert(sb != NULL);
73*839529caSEd Maste 
74*839529caSEd Maste 	ps = sb->sb_ps;
75*839529caSEd Maste 
76*839529caSEd Maste 	STAILQ_REMOVE(&ps->ps_b, sb, _PE_SecBuf, sb_next);
77*839529caSEd Maste 
78*839529caSEd Maste 	if (sb->sb_flags & LIBPE_F_BUFFER_MALLOCED)
79*839529caSEd Maste 		free(sb->sb_pb.pb_buf);
80*839529caSEd Maste 
81*839529caSEd Maste 	free(sb);
82*839529caSEd Maste }
83*839529caSEd Maste 
84*839529caSEd Maste static int
cmp_sb(PE_SecBuf * a,PE_SecBuf * b)85*839529caSEd Maste cmp_sb(PE_SecBuf *a, PE_SecBuf *b)
86*839529caSEd Maste {
87*839529caSEd Maste 
88*839529caSEd Maste 	if (a->sb_pb.pb_off < b->sb_pb.pb_off)
89*839529caSEd Maste 		return (-1);
90*839529caSEd Maste 	else if (a->sb_pb.pb_off == b->sb_pb.pb_off)
91*839529caSEd Maste 		return (0);
92*839529caSEd Maste 	else
93*839529caSEd Maste 		return (1);
94*839529caSEd Maste }
95*839529caSEd Maste 
96*839529caSEd Maste static void
sort_buffers(PE_Scn * ps)97*839529caSEd Maste sort_buffers(PE_Scn *ps)
98*839529caSEd Maste {
99*839529caSEd Maste 
100*839529caSEd Maste 	if (STAILQ_EMPTY(&ps->ps_b))
101*839529caSEd Maste 		return;
102*839529caSEd Maste 
103*839529caSEd Maste 	STAILQ_SORT(&ps->ps_b, _PE_SecBuf, sb_next, cmp_sb);
104*839529caSEd Maste }
105*839529caSEd Maste 
106*839529caSEd Maste size_t
libpe_resync_buffers(PE_Scn * ps)107*839529caSEd Maste libpe_resync_buffers(PE_Scn *ps)
108*839529caSEd Maste {
109*839529caSEd Maste 	PE_SecBuf *sb;
110*839529caSEd Maste 	PE_Buffer *pb;
111*839529caSEd Maste 	size_t sz;
112*839529caSEd Maste 
113*839529caSEd Maste 	assert(ps->ps_flags & LIBPE_F_LOAD_SECTION);
114*839529caSEd Maste 
115*839529caSEd Maste 	sort_buffers(ps);
116*839529caSEd Maste 
117*839529caSEd Maste 	sz = 0;
118*839529caSEd Maste 	STAILQ_FOREACH(sb, &ps->ps_b, sb_next) {
119*839529caSEd Maste 		if (ps->ps_flags & PE_F_DIRTY)
120*839529caSEd Maste 			sb->sb_flags |= PE_F_DIRTY;
121*839529caSEd Maste 
122*839529caSEd Maste 		pb = (PE_Buffer *) sb;
123*839529caSEd Maste 		if (pb->pb_align > ps->ps_falign)
124*839529caSEd Maste 			pb->pb_align = ps->ps_falign;
125*839529caSEd Maste 		if (pb->pb_buf == NULL || pb->pb_size == 0)
126*839529caSEd Maste 			continue;
127*839529caSEd Maste 
128*839529caSEd Maste 		sz = roundup(sz, pb->pb_align);
129*839529caSEd Maste 
130*839529caSEd Maste 		if (pb->pb_off != (off_t) sz) {
131*839529caSEd Maste 			pb->pb_off = sz;
132*839529caSEd Maste 			sb->sb_flags |= PE_F_DIRTY;
133*839529caSEd Maste 		}
134*839529caSEd Maste 		sz += pb->pb_size;
135*839529caSEd Maste 	}
136*839529caSEd Maste 
137*839529caSEd Maste 	return (sz);
138*839529caSEd Maste }
139*839529caSEd Maste 
140*839529caSEd Maste int
libpe_write_buffers(PE_Scn * ps)141*839529caSEd Maste libpe_write_buffers(PE_Scn *ps)
142*839529caSEd Maste {
143*839529caSEd Maste 	PE *pe;
144*839529caSEd Maste 	PE_SecBuf *sb;
145*839529caSEd Maste 	PE_Buffer *pb;
146*839529caSEd Maste 	off_t off;
147*839529caSEd Maste 
148*839529caSEd Maste 	assert(ps->ps_flags & LIBPE_F_LOAD_SECTION);
149*839529caSEd Maste 
150*839529caSEd Maste 	pe = ps->ps_pe;
151*839529caSEd Maste 
152*839529caSEd Maste 	off = 0;
153*839529caSEd Maste 	STAILQ_FOREACH(sb, &ps->ps_b, sb_next) {
154*839529caSEd Maste 		pb = &sb->sb_pb;
155*839529caSEd Maste 		if (pb->pb_buf == NULL || pb->pb_size == 0)
156*839529caSEd Maste 			continue;
157*839529caSEd Maste 
158*839529caSEd Maste 		if ((sb->sb_flags & PE_F_DIRTY) == 0) {
159*839529caSEd Maste 			assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
160*839529caSEd Maste 			if (lseek(pe->pe_fd, (off_t) pb->pb_size, SEEK_CUR) <
161*839529caSEd Maste 			    0) {
162*839529caSEd Maste 				errno = EIO;
163*839529caSEd Maste 				return (-1);
164*839529caSEd Maste 			}
165*839529caSEd Maste 			goto next_buf;
166*839529caSEd Maste 		}
167*839529caSEd Maste 
168*839529caSEd Maste 		if (pb->pb_off > off) {
169*839529caSEd Maste 			if (libpe_pad(pe, pb->pb_off - off) < 0)
170*839529caSEd Maste 				return (-1);
171*839529caSEd Maste 			off = pb->pb_off;
172*839529caSEd Maste 		}
173*839529caSEd Maste 
174*839529caSEd Maste 		if (write(pe->pe_fd, pb->pb_buf, pb->pb_size) !=
175*839529caSEd Maste 		    (ssize_t) pb->pb_size) {
176*839529caSEd Maste 			errno = EIO;
177*839529caSEd Maste 			return (-1);
178*839529caSEd Maste 		}
179*839529caSEd Maste 
180*839529caSEd Maste 	next_buf:
181*839529caSEd Maste 		off += pb->pb_size;
182*839529caSEd Maste 	}
183*839529caSEd Maste 
184*839529caSEd Maste 	return (0);
185*839529caSEd Maste }
186