|
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 "file.h"
|
|
Packit |
b1f7ae |
#include "util.h"
|
|
Packit |
b1f7ae |
#include "yasm.h"
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#include <ctype.h>
|
|
Packit |
b1f7ae |
#include <inttypes.h>
|
|
Packit |
b1f7ae |
#include <stdint.h>
|
|
Packit |
b1f7ae |
#include <stdio.h>
|
|
Packit |
b1f7ae |
#include <stdlib.h>
|
|
Packit |
b1f7ae |
#include <string.h>
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
|
Packit |
b1f7ae |
# define snprintf _snprintf_c
|
|
Packit |
b1f7ae |
#endif
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static int create_section_label_name(char *label, int size, const char *name,
|
|
Packit |
b1f7ae |
const char *attribute)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int written;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
written = snprintf(label, size, "section_%s_%s", name, attribute);
|
|
Packit |
b1f7ae |
if (size <= written)
|
|
Packit |
b1f7ae |
return -err_no_mem;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static int add_section_label(struct label *l, const char *name,
|
|
Packit |
b1f7ae |
const char *attribute, uint64_t value,
|
|
Packit |
b1f7ae |
struct label **length)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
char label[255];
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = create_section_label_name(label, sizeof(label), name,
|
|
Packit |
b1f7ae |
attribute);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = l_append(l, label, value);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (length)
|
|
Packit |
b1f7ae |
*length = l_find(l, label);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static int parse_section_label(struct label *l, const char *name,
|
|
Packit |
b1f7ae |
const char *attribute)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
uint64_t addr;
|
|
Packit |
b1f7ae |
char *value;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
value = strtok(NULL, " ]");
|
|
Packit |
b1f7ae |
if (!value)
|
|
Packit |
b1f7ae |
return -err_section_attribute_no_value;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (sscanf(value, "%" PRIx64, &addr) != 1)
|
|
Packit |
b1f7ae |
return -err_parse_int;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return add_section_label(l, name, attribute, addr, NULL);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static int parse_section(char *line, struct label *l, struct label **length)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
char *name, *attribute;
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
name = strtok(line, " ");
|
|
Packit |
b1f7ae |
if (!name)
|
|
Packit |
b1f7ae |
return -err_section_no_name;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* we initialize the section's length to zero - it will be updated
|
|
Packit |
b1f7ae |
* when we process the section's content.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
errcode = add_section_label(l, name, "length", 0ull, length);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
for (;;) {
|
|
Packit |
b1f7ae |
attribute = strtok(NULL, " =]");
|
|
Packit |
b1f7ae |
if (!attribute)
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (strcmp(attribute, "start") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_section_label(l, name, "start");
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
} else if (strcmp(attribute, "vstart") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_section_label(l, name, "vstart");
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
} else
|
|
Packit |
b1f7ae |
return -err_section_unknown_attribute;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static int lookup_section_label(struct label *l, const char *name,
|
|
Packit |
b1f7ae |
const char *attribute, uint64_t *value)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
char label[255];
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = create_section_label_name(label, sizeof(label), name,
|
|
Packit |
b1f7ae |
attribute);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return l_lookup(l, value, label);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static int lookup_section_vstart(struct label *l, char *line,
|
|
Packit |
b1f7ae |
uint64_t *vstart)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
char *name;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
name = strtok(line, " ");
|
|
Packit |
b1f7ae |
if (!name)
|
|
Packit |
b1f7ae |
return -err_section_no_name;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return lookup_section_label(l, name, "vstart", vstart);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int parse_yasm_labels(struct label *l, const struct text *t)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int errcode, no_org_directive;
|
|
Packit |
b1f7ae |
size_t i;
|
|
Packit |
b1f7ae |
uint64_t base_addr;
|
|
Packit |
b1f7ae |
enum { linelen = 1024 };
|
|
Packit |
b1f7ae |
char line[linelen];
|
|
Packit |
b1f7ae |
struct label *length;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!t))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
base_addr = 0;
|
|
Packit |
b1f7ae |
no_org_directive = 1;
|
|
Packit |
b1f7ae |
length = NULL;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* determine base address from org directive and insert special
|
|
Packit |
b1f7ae |
* section labels.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
for (i = 0; i < t->n; i++) {
|
|
Packit |
b1f7ae |
char *tmp;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = text_line(t, line, linelen, i);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
tmp = strstr(line, "[section");
|
|
Packit |
b1f7ae |
if (tmp) {
|
|
Packit |
b1f7ae |
tmp += strlen("[section");
|
|
Packit |
b1f7ae |
errcode = parse_section(tmp, l, &length);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
tmp = strstr(line, "[org");
|
|
Packit |
b1f7ae |
if (tmp) {
|
|
Packit |
b1f7ae |
base_addr = strtol(tmp+strlen("[org"), NULL, 0);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = l_append(l, "org", base_addr);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
no_org_directive = 0;
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* update the section_<name>_length label, if we have one.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* this must be last; it destroys @line.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
if (length) {
|
|
Packit |
b1f7ae |
uint64_t value, size;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
tmp = strtok(line, " ");
|
|
Packit |
b1f7ae |
if (!tmp)
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* we expect a line number. */
|
|
Packit |
b1f7ae |
errcode = str_to_uint64(tmp, &value, 10);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
tmp = strtok(NULL, " ");
|
|
Packit |
b1f7ae |
if (!tmp)
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* we expect an address. */
|
|
Packit |
b1f7ae |
errcode = str_to_uint64(tmp, &value, 16);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
tmp = strtok(NULL, " ");
|
|
Packit |
b1f7ae |
if (!tmp)
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* we expect an opcode. */
|
|
Packit |
b1f7ae |
errcode = str_to_uint64(tmp, &value, 16);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* we got an opcode - let's compute it's size. */
|
|
Packit |
b1f7ae |
for (size = 0; value != 0; value >>= 8)
|
|
Packit |
b1f7ae |
size += 1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* update the section_<name>_length label. */
|
|
Packit |
b1f7ae |
length->addr += size;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (no_org_directive)
|
|
Packit |
b1f7ae |
return -err_no_org_directive;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
for (i = 0; i < t->n; i++) {
|
|
Packit |
b1f7ae |
char *tmp, *name;
|
|
Packit |
b1f7ae |
uint64_t addr;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = text_line(t, line, linelen, i);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Change the base on section switches. */
|
|
Packit |
b1f7ae |
tmp = strstr(line, "[section");
|
|
Packit |
b1f7ae |
if (tmp) {
|
|
Packit |
b1f7ae |
tmp += strlen("[section");
|
|
Packit |
b1f7ae |
errcode = lookup_section_vstart(l, tmp, &base_addr);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* skip line number count. */
|
|
Packit |
b1f7ae |
tmp = strtok(line, " ");
|
|
Packit |
b1f7ae |
if (!tmp)
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* the label can now be on the same line as the memory
|
|
Packit |
b1f7ae |
* address or on a line by its own.
|
|
Packit |
b1f7ae |
* we look at the next token and (1) if it looks like a
|
|
Packit |
b1f7ae |
* label, we search in the following lines for the
|
|
Packit |
b1f7ae |
* corresponding address; or (2) if it looks like an
|
|
Packit |
b1f7ae |
* address, we store it and see if the token after the
|
|
Packit |
b1f7ae |
* opcode looks like a token; or (3) none of the above,
|
|
Packit |
b1f7ae |
* we continue with the next line.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* second token after the line number count. it's
|
|
Packit |
b1f7ae |
* either an address; or a label.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
tmp = strtok(NULL, " ");
|
|
Packit |
b1f7ae |
if (!tmp)
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (!make_label(tmp)) {
|
|
Packit |
b1f7ae |
/* get address in case we find a label later. */
|
|
Packit |
b1f7ae |
if (sscanf(tmp, "%" PRIx64, &addr) != 1)
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* skip the opcode token. */
|
|
Packit |
b1f7ae |
tmp = strtok(NULL, " ");
|
|
Packit |
b1f7ae |
if (!tmp)
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* this might be a label now. */
|
|
Packit |
b1f7ae |
tmp = strtok(NULL, " ");
|
|
Packit |
b1f7ae |
if (!make_label(tmp))
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = l_append(l, tmp, addr + base_addr);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
name = duplicate_str(tmp);
|
|
Packit |
b1f7ae |
if (!name) {
|
|
Packit |
b1f7ae |
errcode = -err_no_mem;
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* there was a label so now an address needs to
|
|
Packit |
b1f7ae |
* be found.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
errcode = -err_label_addr;
|
|
Packit |
b1f7ae |
for (i += 1; i < t->n; i++) {
|
|
Packit |
b1f7ae |
int errcode_text;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode_text = text_line(t, line, linelen, i);
|
|
Packit |
b1f7ae |
if (errcode_text < 0) {
|
|
Packit |
b1f7ae |
errcode = errcode_text;
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
if (sscanf(line, "%*d %" PRIx64 " %*x %*s", &addr)
|
|
Packit |
b1f7ae |
== 1) {
|
|
Packit |
b1f7ae |
errcode = l_append(l, name, addr + base_addr);
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
if (errcode == -err_label_addr)
|
|
Packit |
b1f7ae |
fprintf(stderr, "label '%s' has no address\n", name);
|
|
Packit |
b1f7ae |
free(name);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
error:
|
|
Packit |
b1f7ae |
l_free(l->next);
|
|
Packit |
b1f7ae |
free(l->name);
|
|
Packit |
b1f7ae |
l->next = NULL;
|
|
Packit |
b1f7ae |
l->name = NULL;
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int make_label(char *s)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
size_t n;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!s))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
n = strlen(s);
|
|
Packit |
b1f7ae |
if (n == 0 || s[n-1] != ':')
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
s[n-1] = '\0';
|
|
Packit |
b1f7ae |
return 1;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
struct state *st_alloc(void)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
return calloc(1, sizeof(struct state));
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
void st_free(struct state *st)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (!st)
|
|
Packit |
b1f7ae |
return;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
free(st->filename);
|
|
Packit |
b1f7ae |
free(st->line);
|
|
Packit |
b1f7ae |
free(st);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int st_print_err(const struct state *st, const char *s, int errcode)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (bug_on(!st))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!(-err_max < errcode && errcode < 0)))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (!s)
|
|
Packit |
b1f7ae |
s = "";
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
fprintf(stderr, "%s:%d: error: %s (%s)\n", st->filename, st->n-1, s,
|
|
Packit |
b1f7ae |
errstr[-errcode]);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Sets current @filename, increment (@inc) and line number (@n) in @st.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Note that @filename, @inc and @n correspond to the yasm .lst file
|
|
Packit |
b1f7ae |
* source file information.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns 0 on success; a negative enum errcode otherwise.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
static int st_set_file(struct state *st, const char *filename, int inc, int n)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (bug_on(!st))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!filename))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
free(st->filename);
|
|
Packit |
b1f7ae |
st->filename = duplicate_str(filename);
|
|
Packit |
b1f7ae |
if (!st->filename)
|
|
Packit |
b1f7ae |
return -err_no_mem;
|
|
Packit |
b1f7ae |
st->inc = inc;
|
|
Packit |
b1f7ae |
st->n = n;
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Sets current line in @st to @s and increases the line number.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns 0 on success; a negative enum errcode otherwise.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
static int st_update(struct state *st, const char *s)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
free(st->line);
|
|
Packit |
b1f7ae |
st->line = duplicate_str(s);
|
|
Packit |
b1f7ae |
if (!st->line)
|
|
Packit |
b1f7ae |
return -err_no_mem;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
st->n += st->inc;
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
struct pt_directive *pd_alloc(size_t n)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
struct pt_directive *pd;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
pd = calloc(1, sizeof(*pd));
|
|
Packit |
b1f7ae |
if (!pd)
|
|
Packit |
b1f7ae |
return NULL;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
pd->name = malloc(n);
|
|
Packit |
b1f7ae |
if (!pd->name)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
pd->payload = malloc(n);
|
|
Packit |
b1f7ae |
if (!pd->payload)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
pd->nlen = n;
|
|
Packit |
b1f7ae |
pd->plen = n;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return pd;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
error:
|
|
Packit |
b1f7ae |
pd_free(pd);
|
|
Packit |
b1f7ae |
return NULL;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
void pd_free(struct pt_directive *pd)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (!pd)
|
|
Packit |
b1f7ae |
return;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
free(pd->name);
|
|
Packit |
b1f7ae |
free(pd->payload);
|
|
Packit |
b1f7ae |
free(pd);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int pd_set(struct pt_directive *pd, const char *name, const char *payload)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (bug_on(!pd))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!name))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!payload))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
strncpy(pd->name, name, pd->nlen);
|
|
Packit |
b1f7ae |
if (pd->nlen > 0)
|
|
Packit |
b1f7ae |
pd->name[pd->nlen - 1] = '\0';
|
|
Packit |
b1f7ae |
strncpy(pd->payload, payload, pd->plen);
|
|
Packit |
b1f7ae |
if (pd->plen > 0)
|
|
Packit |
b1f7ae |
pd->payload[pd->plen - 1] = '\0';
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Magic annotation marker. */
|
|
Packit |
b1f7ae |
const char *marker = "@pt ";
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int pd_parse(struct pt_directive *pd, struct state *st)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
char *line, *comment, *ptdirective, *openpar, *closepar;
|
|
Packit |
b1f7ae |
char *directive, *payload;
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
char *c;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!pd))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!st))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
line = duplicate_str(st->line);
|
|
Packit |
b1f7ae |
if (!line)
|
|
Packit |
b1f7ae |
return -err_no_mem;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* make line lower case. */
|
|
Packit |
b1f7ae |
for (c = line; *c; ++c)
|
|
Packit |
b1f7ae |
*c = (char) tolower(*c);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* if the current line is not a comment or contains no magic marker
|
|
Packit |
b1f7ae |
* -err_no_directive is returned.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
errcode = -err_no_directive;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* search where the comment begins. */
|
|
Packit |
b1f7ae |
comment = strchr(line, ';');
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* if there is no comment in the line, we don't have anything to
|
|
Packit |
b1f7ae |
* do.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
if (!comment)
|
|
Packit |
b1f7ae |
goto cleanup;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* search for @pt marker. */
|
|
Packit |
b1f7ae |
ptdirective = strstr(comment+1, marker);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* if there is no such marker in the comment, we don't have
|
|
Packit |
b1f7ae |
* anything to do.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
if (!ptdirective)
|
|
Packit |
b1f7ae |
goto cleanup;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* directive found, now parse the payload. */
|
|
Packit |
b1f7ae |
errcode = 0;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* find position of next '(', separating the directive and the
|
|
Packit |
b1f7ae |
* payload.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
openpar = strchr(ptdirective, '(');
|
|
Packit |
b1f7ae |
if (!openpar) {
|
|
Packit |
b1f7ae |
errcode = -err_missing_openpar;
|
|
Packit |
b1f7ae |
st_print_err(st, "invalid syntax", errcode);
|
|
Packit |
b1f7ae |
goto cleanup;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* find position of next ')', marking the end of the payload */
|
|
Packit |
b1f7ae |
closepar = strchr(openpar, ')');
|
|
Packit |
b1f7ae |
if (!closepar) {
|
|
Packit |
b1f7ae |
errcode = -err_missing_closepar;
|
|
Packit |
b1f7ae |
st_print_err(st, "invalid syntax", errcode);
|
|
Packit |
b1f7ae |
goto cleanup;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* make "multiple" strings by artifically terminating them with
|
|
Packit |
b1f7ae |
* '\0' then get directive and payload substrings, which will
|
|
Packit |
b1f7ae |
* have leading and trailing whitespace "removed".
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
*openpar = '\0';
|
|
Packit |
b1f7ae |
*closepar = '\0';
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* skip leading whitespace. */
|
|
Packit |
b1f7ae |
directive = ptdirective + strlen(marker);
|
|
Packit |
b1f7ae |
while (isspace(*directive))
|
|
Packit |
b1f7ae |
directive += 1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
payload = openpar+1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = pd_set(pd, directive, payload);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
cleanup:
|
|
Packit |
b1f7ae |
free(line);
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
const char *bin_suffix = ".bin";
|
|
Packit |
b1f7ae |
const char *lst_suffix = ".lst";
|
|
Packit |
b1f7ae |
const char path_separator = '/';
|
|
Packit |
b1f7ae |
enum {
|
|
Packit |
b1f7ae |
max_filename_len = 1024
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
struct yasm *yasm_alloc(const char *pttfile)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
char *tmp;
|
|
Packit |
b1f7ae |
size_t n;
|
|
Packit |
b1f7ae |
struct yasm *y;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!pttfile))
|
|
Packit |
b1f7ae |
return NULL;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
y = calloc(1, sizeof(*y));
|
|
Packit |
b1f7ae |
if (!y)
|
|
Packit |
b1f7ae |
return NULL;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
y->fl = fl_alloc();
|
|
Packit |
b1f7ae |
if (!y->fl)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
y->st_asm = st_alloc();
|
|
Packit |
b1f7ae |
if (!y->st_asm)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
y->fileroot = duplicate_str(pttfile);
|
|
Packit |
b1f7ae |
if (!y->fileroot)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
y->pttfile = duplicate_str(pttfile);
|
|
Packit |
b1f7ae |
if (!y->pttfile)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
tmp = strrchr(y->fileroot, '.');
|
|
Packit |
b1f7ae |
if (tmp)
|
|
Packit |
b1f7ae |
*tmp = '\0';
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
tmp = strrchr(y->fileroot, path_separator);
|
|
Packit |
b1f7ae |
if (tmp) {
|
|
Packit |
b1f7ae |
tmp += 1;
|
|
Packit |
b1f7ae |
memmove(y->fileroot, tmp, strlen(tmp)+1);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
y->binfile = malloc(strlen(y->fileroot)+strlen(bin_suffix)+1);
|
|
Packit |
b1f7ae |
if (!y->binfile)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
y->lstfile = malloc(strlen(y->fileroot)+strlen(lst_suffix)+1);
|
|
Packit |
b1f7ae |
if (!y->lstfile)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
n = strlen(y->fileroot);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
strcpy(y->binfile, y->fileroot);
|
|
Packit |
b1f7ae |
strcpy(y->binfile+n, bin_suffix);
|
|
Packit |
b1f7ae |
strcpy(y->lstfile, y->fileroot);
|
|
Packit |
b1f7ae |
strcpy(y->lstfile+n, lst_suffix);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
y->l = l_alloc();
|
|
Packit |
b1f7ae |
if (!y->l)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return y;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
error:
|
|
Packit |
b1f7ae |
yasm_free(y);
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static int yasm_run(struct yasm *y)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
char *argv[] = {
|
|
Packit |
b1f7ae |
"yasm",
|
|
Packit |
b1f7ae |
"<pttfile>",
|
|
Packit |
b1f7ae |
"-f", "bin",
|
|
Packit |
b1f7ae |
"-o", "<binfile>",
|
|
Packit |
b1f7ae |
"-L", "nasm",
|
|
Packit |
b1f7ae |
"-l", "<lstfile>",
|
|
Packit |
b1f7ae |
NULL,
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
argv[1] = y->pttfile;
|
|
Packit |
b1f7ae |
argv[5] = y->binfile;
|
|
Packit |
b1f7ae |
argv[9] = y->lstfile;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return run(argv[0], argv);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int yasm_parse(struct yasm *y)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
const struct text *t;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!y))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = yasm_run(y);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = fl_gettext(y->fl, &t, y->lstfile);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = parse_yasm_labels(y->l, t);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
error:
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
void yasm_free(struct yasm *y)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (!y)
|
|
Packit |
b1f7ae |
return;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
free(y->fileroot);
|
|
Packit |
b1f7ae |
free(y->pttfile);
|
|
Packit |
b1f7ae |
free(y->lstfile);
|
|
Packit |
b1f7ae |
free(y->binfile);
|
|
Packit |
b1f7ae |
fl_free(y->fl);
|
|
Packit |
b1f7ae |
st_free(y->st_asm);
|
|
Packit |
b1f7ae |
l_free(y->l);
|
|
Packit |
b1f7ae |
free(y);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int yasm_lookup_label(const struct yasm *y, uint64_t *addr,
|
|
Packit |
b1f7ae |
const char *labelname)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (bug_on(!y))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return l_lookup(y->l, addr, labelname);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static int yasm_advance_next_line(struct yasm *y)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
enum { slen = 1024 };
|
|
Packit |
b1f7ae |
char s[slen];
|
|
Packit |
b1f7ae |
char filename[max_filename_len];
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
int asm_line, asm_inc;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!y))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
for (;;) {
|
|
Packit |
b1f7ae |
errcode = fl_getline(y->fl, s, slen, y->lstfile,
|
|
Packit |
b1f7ae |
y->lst_curr_line);
|
|
Packit |
b1f7ae |
/* always advance in lst file. */
|
|
Packit |
b1f7ae |
y->lst_curr_line += 1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* if the current lst file line is a line directive, set
|
|
Packit |
b1f7ae |
* state information to this file, line and increment
|
|
Packit |
b1f7ae |
* and continue.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
if (sscanf(s, "%*d %%line %d+%d %1023[^\r\n]", &asm_line,
|
|
Packit |
b1f7ae |
&asm_inc, filename) == 3) {
|
|
Packit |
b1f7ae |
st_set_file(y->st_asm, filename, asm_line, asm_inc);
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* if line number or increment in the previous line
|
|
Packit |
b1f7ae |
* directive is <= 0, the current lst line has no
|
|
Packit |
b1f7ae |
* corresponding line in the source file.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
if (y->st_asm->n <= 0 || y->st_asm->inc <= 0)
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* finally the current line in the lst file can be
|
|
Packit |
b1f7ae |
* correlated to the source file, so we retrieve the
|
|
Packit |
b1f7ae |
* line from it and update the state.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
errcode = fl_getline(y->fl, s, slen, y->st_asm->filename,
|
|
Packit |
b1f7ae |
y->st_asm->n-1);
|
|
Packit |
b1f7ae |
st_update(y->st_asm, s);
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int yasm_pd_parse(struct yasm *y, struct pt_directive *pd)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
return pd_parse(pd, y->st_asm);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int yasm_next_pt_directive(struct yasm *y, struct pt_directive *pd)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
for (;;) {
|
|
Packit |
b1f7ae |
errcode = yasm_advance_next_line(y);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = pd_parse(pd, y->st_asm);
|
|
Packit |
b1f7ae |
if (errcode != -err_no_directive)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
if (errcode == -err_out_of_range)
|
|
Packit |
b1f7ae |
errcode = -err_no_directive;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int yasm_next_line(struct yasm *y, char *dest, size_t destlen)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (!destlen)
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!dest))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = yasm_advance_next_line(y);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
strncpy(dest, y->st_asm->line, destlen);
|
|
Packit |
b1f7ae |
dest[destlen-1] = '\0';
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int yasm_print_err(const struct yasm *y, const char *s, int errcode)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (bug_on(!y))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return st_print_err(y->st_asm, s, errcode);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int yasm_lookup_section_label(const struct yasm *y, const char *name,
|
|
Packit |
b1f7ae |
const char *attribute, uint64_t *value)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (bug_on(!y))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return lookup_section_label(y->l, name, attribute, value);
|
|
Packit |
b1f7ae |
}
|