|
Packit |
b1f7ae |
/*
|
|
Packit |
b1f7ae |
* Copyright (c) 2013-2017, Intel Corporation
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Redistribution and use in source and binary forms, with or without
|
|
Packit |
b1f7ae |
* modification, are permitted provided that the following conditions are met:
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* * Redistributions of source code must retain the above copyright notice,
|
|
Packit |
b1f7ae |
* this list of conditions and the following disclaimer.
|
|
Packit |
b1f7ae |
* * Redistributions in binary form must reproduce the above copyright notice,
|
|
Packit |
b1f7ae |
* this list of conditions and the following disclaimer in the documentation
|
|
Packit |
b1f7ae |
* and/or other materials provided with the distribution.
|
|
Packit |
b1f7ae |
* * Neither the name of Intel Corporation nor the names of its contributors
|
|
Packit |
b1f7ae |
* may be used to endorse or promote products derived from this software
|
|
Packit |
b1f7ae |
* without specific prior written permission.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit |
b1f7ae |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
b1f7ae |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit |
b1f7ae |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
Packit |
b1f7ae |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
Packit |
b1f7ae |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
Packit |
b1f7ae |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
Packit |
b1f7ae |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
Packit |
b1f7ae |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
Packit |
b1f7ae |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
Packit |
b1f7ae |
* POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#include "errcode.h"
|
|
Packit |
b1f7ae |
#include "util.h"
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#include <ctype.h>
|
|
Packit |
b1f7ae |
#include <errno.h>
|
|
Packit |
b1f7ae |
#include <stdio.h>
|
|
Packit |
b1f7ae |
#include <stdlib.h>
|
|
Packit |
b1f7ae |
#include <string.h>
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
char *duplicate_str(const char *s)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
char *dup;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (!s)
|
|
Packit |
b1f7ae |
return NULL;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
dup = malloc(strlen(s)+1);
|
|
Packit |
b1f7ae |
if (!dup)
|
|
Packit |
b1f7ae |
return NULL;
|
|
Packit |
b1f7ae |
return strcpy(dup, s);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int str_to_uint64(const char *str, uint64_t *val, int base)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
char *endptr;
|
|
Packit |
b1f7ae |
uint64_t x;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (!str || !val)
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errno = 0;
|
|
Packit |
b1f7ae |
x = strtoull(str, &endptr, base);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (errno == EINVAL)
|
|
Packit |
b1f7ae |
return -err_parse_int;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (errno == ERANGE)
|
|
Packit |
b1f7ae |
return -err_parse_int_too_big;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (str == endptr || *endptr != '\0')
|
|
Packit |
b1f7ae |
return -err_parse_int;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
*val = x;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int str_to_uint32(const char *str, uint32_t *val, int base)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
uint64_t x;
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (!str || !val)
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = str_to_uint64(str, &x, base);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (UINT32_MAX < x)
|
|
Packit |
b1f7ae |
return -err_parse_int_too_big;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
*val = (uint32_t) x;
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int str_to_uint16(const char *str, uint16_t *val, int base)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
uint64_t x;
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (!str || !val)
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = str_to_uint64(str, &x, base);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (UINT16_MAX < x)
|
|
Packit |
b1f7ae |
return -err_parse_int_too_big;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
*val = (uint16_t) x;
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int str_to_uint8(const char *str, uint8_t *val, int base)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
uint64_t x;
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (!str || !val)
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = str_to_uint64(str, &x, base);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (UINT8_MAX < x)
|
|
Packit |
b1f7ae |
return -err_parse_int_too_big;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
*val = (uint8_t) x;
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int do_bug_on(int cond, const char *condstr, const char *file, int line)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (cond)
|
|
Packit |
b1f7ae |
fprintf(stderr, "%s:%d: internal error: %s\n", file, line,
|
|
Packit |
b1f7ae |
condstr);
|
|
Packit |
b1f7ae |
return cond;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
struct label *l_alloc(void)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
return calloc(1, sizeof(struct label));
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
void l_free(struct label *l)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (!l)
|
|
Packit |
b1f7ae |
return;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
l_free(l->next);
|
|
Packit |
b1f7ae |
free(l->name);
|
|
Packit |
b1f7ae |
free(l);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int l_append(struct label *l, const char *name, uint64_t addr)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!l))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!name))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* skip to the last label. */
|
|
Packit |
b1f7ae |
while (l->next) {
|
|
Packit |
b1f7ae |
l = l->next;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* ignore the first label, which has no name. */
|
|
Packit |
b1f7ae |
if (strcmp(l->name, name) == 0)
|
|
Packit |
b1f7ae |
return -err_label_not_unique;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* append a new label. */
|
|
Packit |
b1f7ae |
l->next = l_alloc();
|
|
Packit |
b1f7ae |
if (!l->next)
|
|
Packit |
b1f7ae |
return -err_no_mem;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* save the name. */
|
|
Packit |
b1f7ae |
l->next->name = duplicate_str(name);
|
|
Packit |
b1f7ae |
if (!l->next->name) {
|
|
Packit |
b1f7ae |
errcode = -err_no_mem;
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* save the address. */
|
|
Packit |
b1f7ae |
l->next->addr = addr;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
error:
|
|
Packit |
b1f7ae |
free(l->next->name);
|
|
Packit |
b1f7ae |
free(l->next);
|
|
Packit |
b1f7ae |
l->next = NULL;
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int l_lookup(const struct label *l, uint64_t *addr,
|
|
Packit |
b1f7ae |
const char *name)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (bug_on(!l))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!addr))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!name))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
*addr = 0;
|
|
Packit |
b1f7ae |
while (l->next) {
|
|
Packit |
b1f7ae |
l = l->next;
|
|
Packit |
b1f7ae |
if (strcmp(l->name, name) == 0) {
|
|
Packit |
b1f7ae |
*addr = l->addr;
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
return -err_no_label;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
struct label *l_find(struct label *l, const char *name)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (bug_on(!l))
|
|
Packit |
b1f7ae |
return NULL;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!name))
|
|
Packit |
b1f7ae |
return NULL;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
while (l->next) {
|
|
Packit |
b1f7ae |
l = l->next;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!l->name))
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (strcmp(l->name, name) == 0)
|
|
Packit |
b1f7ae |
return l;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
return NULL;
|
|
Packit |
b1f7ae |
}
|