Path: blob/main/contrib/elftoolchain/libpe/libpe_buffer.c
39483 views
/*-1* Copyright (c) 2016 Kai Wang2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526#include <sys/param.h>27#include <assert.h>28#include <errno.h>29#include <stdlib.h>30#include <unistd.h>3132#include "_libpe.h"3334ELFTC_VCSID("$Id: libpe_buffer.c 3312 2016-01-10 09:23:51Z kaiwang27 $");3536PE_SecBuf *37libpe_alloc_buffer(PE_Scn *ps, size_t sz)38{39PE_SecBuf *sb;4041if ((sb = malloc(sizeof(PE_SecBuf))) == NULL) {42errno = ENOMEM;43return (NULL);44}4546sb->sb_ps = ps;47sb->sb_flags = 0;48sb->sb_pb.pb_align = 1;49sb->sb_pb.pb_off = 0;50sb->sb_pb.pb_size = sz;51if (sz > 0) {52if ((sb->sb_pb.pb_buf = malloc(sz)) == NULL) {53free(sb);54errno = ENOMEM;55return (NULL);56}57sb->sb_flags |= LIBPE_F_BUFFER_MALLOCED;58} else59sb->sb_pb.pb_buf = NULL;6061STAILQ_INSERT_TAIL(&ps->ps_b, sb, sb_next);6263return (sb);64}6566void67libpe_release_buffer(PE_SecBuf *sb)68{69PE_Scn *ps;7071assert(sb != NULL);7273ps = sb->sb_ps;7475STAILQ_REMOVE(&ps->ps_b, sb, _PE_SecBuf, sb_next);7677if (sb->sb_flags & LIBPE_F_BUFFER_MALLOCED)78free(sb->sb_pb.pb_buf);7980free(sb);81}8283static int84cmp_sb(PE_SecBuf *a, PE_SecBuf *b)85{8687if (a->sb_pb.pb_off < b->sb_pb.pb_off)88return (-1);89else if (a->sb_pb.pb_off == b->sb_pb.pb_off)90return (0);91else92return (1);93}9495static void96sort_buffers(PE_Scn *ps)97{9899if (STAILQ_EMPTY(&ps->ps_b))100return;101102STAILQ_SORT(&ps->ps_b, _PE_SecBuf, sb_next, cmp_sb);103}104105size_t106libpe_resync_buffers(PE_Scn *ps)107{108PE_SecBuf *sb;109PE_Buffer *pb;110size_t sz;111112assert(ps->ps_flags & LIBPE_F_LOAD_SECTION);113114sort_buffers(ps);115116sz = 0;117STAILQ_FOREACH(sb, &ps->ps_b, sb_next) {118if (ps->ps_flags & PE_F_DIRTY)119sb->sb_flags |= PE_F_DIRTY;120121pb = (PE_Buffer *) sb;122if (pb->pb_align > ps->ps_falign)123pb->pb_align = ps->ps_falign;124if (pb->pb_buf == NULL || pb->pb_size == 0)125continue;126127sz = roundup(sz, pb->pb_align);128129if (pb->pb_off != (off_t) sz) {130pb->pb_off = sz;131sb->sb_flags |= PE_F_DIRTY;132}133sz += pb->pb_size;134}135136return (sz);137}138139int140libpe_write_buffers(PE_Scn *ps)141{142PE *pe;143PE_SecBuf *sb;144PE_Buffer *pb;145off_t off;146147assert(ps->ps_flags & LIBPE_F_LOAD_SECTION);148149pe = ps->ps_pe;150151off = 0;152STAILQ_FOREACH(sb, &ps->ps_b, sb_next) {153pb = &sb->sb_pb;154if (pb->pb_buf == NULL || pb->pb_size == 0)155continue;156157if ((sb->sb_flags & PE_F_DIRTY) == 0) {158assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);159if (lseek(pe->pe_fd, (off_t) pb->pb_size, SEEK_CUR) <1600) {161errno = EIO;162return (-1);163}164goto next_buf;165}166167if (pb->pb_off > off) {168if (libpe_pad(pe, pb->pb_off - off) < 0)169return (-1);170off = pb->pb_off;171}172173if (write(pe->pe_fd, pb->pb_buf, pb->pb_size) !=174(ssize_t) pb->pb_size) {175errno = EIO;176return (-1);177}178179next_buf:180off += pb->pb_size;181}182183return (0);184}185186187