|
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 "parse.h"
|
|
Packit |
b1f7ae |
#include "util.h"
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
#include <ctype.h>
|
|
Packit |
b1f7ae |
#include <stdio.h>
|
|
Packit |
b1f7ae |
#include <stdlib.h>
|
|
Packit |
b1f7ae |
#include <string.h>
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
const char *pt_suffix = ".pt";
|
|
Packit |
b1f7ae |
const char *exp_suffix = ".exp";
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
enum {
|
|
Packit |
b1f7ae |
pd_len = 1024
|
|
Packit |
b1f7ae |
};
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Deallocates the memory used by @p, closes all files, clears and
|
|
Packit |
b1f7ae |
* zeroes the fields.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
static void p_free(struct parser *p)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (!p)
|
|
Packit |
b1f7ae |
return;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
yasm_free(p->y);
|
|
Packit |
b1f7ae |
pd_free(p->pd);
|
|
Packit |
b1f7ae |
l_free(p->pt_labels);
|
|
Packit |
b1f7ae |
free(p->ptfilename);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
free(p);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Initializes @p with @pttfile and @conf.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns 0 on success; a negative enum errcode otherwise.
|
|
Packit |
b1f7ae |
* Returns -err_internal if @p is the NULL pointer.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
static struct parser *p_alloc(const char *pttfile, const struct pt_config *conf)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
size_t n;
|
|
Packit |
b1f7ae |
struct parser *p;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (!conf)
|
|
Packit |
b1f7ae |
return NULL;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (!pttfile)
|
|
Packit |
b1f7ae |
return NULL;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
p = calloc(1, sizeof(*p));
|
|
Packit |
b1f7ae |
if (!p)
|
|
Packit |
b1f7ae |
return NULL;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
p->y = yasm_alloc(pttfile);
|
|
Packit |
b1f7ae |
if (!p->y)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
n = strlen(p->y->fileroot) + 1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
p->ptfilename = malloc(n+strlen(pt_suffix));
|
|
Packit |
b1f7ae |
if (!p->ptfilename)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
strcpy(p->ptfilename, p->y->fileroot);
|
|
Packit |
b1f7ae |
strcat(p->ptfilename, pt_suffix);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
p->pd = pd_alloc(pd_len);
|
|
Packit |
b1f7ae |
if (!p->pd)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
p->pt_labels = l_alloc();
|
|
Packit |
b1f7ae |
if (!p->pt_labels)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
p->conf = conf;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return p;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
error:
|
|
Packit |
b1f7ae |
p_free(p);
|
|
Packit |
b1f7ae |
return NULL;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Generates an .exp filename following the scheme:
|
|
Packit |
b1f7ae |
* <fileroot>[-<extra>].exp
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
static char *expfilename(struct parser *p, const char *extra)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
char *filename;
|
|
Packit |
b1f7ae |
/* reserve enough space to hold the string
|
|
Packit |
b1f7ae |
* "-cpu_fffff_mmm_sss" + 1 for the trailing null character.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
char cpu_suffix[19];
|
|
Packit |
b1f7ae |
size_t n;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (!extra)
|
|
Packit |
b1f7ae |
extra = "";
|
|
Packit |
b1f7ae |
*cpu_suffix = '\0';
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* determine length of resulting filename, which looks like:
|
|
Packit |
b1f7ae |
* <fileroot>[-<extra>][-cpu_<f>_<m>_<s>].exp
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
n = strlen(p->y->fileroot);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (*extra != '\0')
|
|
Packit |
b1f7ae |
/* the extra string is prepended with a -. */
|
|
Packit |
b1f7ae |
n += 1 + strlen(extra);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (p->conf->cpu.vendor != pcv_unknown) {
|
|
Packit |
b1f7ae |
struct pt_cpu cpu;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
cpu = p->conf->cpu;
|
|
Packit |
b1f7ae |
if (cpu.stepping)
|
|
Packit |
b1f7ae |
n += sprintf(cpu_suffix,
|
|
Packit |
b1f7ae |
"-cpu_%" PRIu16 "_%" PRIu8 "_%" PRIu8 "",
|
|
Packit |
b1f7ae |
cpu.family, cpu.model, cpu.stepping);
|
|
Packit |
b1f7ae |
else
|
|
Packit |
b1f7ae |
n += sprintf(cpu_suffix,
|
|
Packit |
b1f7ae |
"-cpu_%" PRIu16 "_%" PRIu8 "", cpu.family,
|
|
Packit |
b1f7ae |
cpu.model);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
n += strlen(exp_suffix);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* trailing null character. */
|
|
Packit |
b1f7ae |
n += 1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
filename = malloc(n);
|
|
Packit |
b1f7ae |
if (!filename)
|
|
Packit |
b1f7ae |
return NULL;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
strcpy(filename, p->y->fileroot);
|
|
Packit |
b1f7ae |
if (*extra != '\0') {
|
|
Packit |
b1f7ae |
strcat(filename, "-");
|
|
Packit |
b1f7ae |
strcat(filename, extra);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
strcat(filename, cpu_suffix);
|
|
Packit |
b1f7ae |
strcat(filename, exp_suffix);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return filename;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Returns true if @c is part of a label; false otherwise. */
|
|
Packit |
b1f7ae |
static int islabelchar(int c)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (isalnum(c))
|
|
Packit |
b1f7ae |
return 1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
switch (c) {
|
|
Packit |
b1f7ae |
case '_':
|
|
Packit |
b1f7ae |
return 1;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Generates the content of the .exp file by printing all lines with
|
|
Packit |
b1f7ae |
* everything up to and including the first comment semicolon removed.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns 0 on success; a negative enum errcode otherwise.
|
|
Packit |
b1f7ae |
* Returns -err_internal if @p is the NULL pointer.
|
|
Packit |
b1f7ae |
* Returns -err_file_write if the .exp file could not be fully written.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
static int p_gen_expfile(struct parser *p)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
enum { slen = 1024 };
|
|
Packit |
b1f7ae |
char s[slen];
|
|
Packit |
b1f7ae |
struct pt_directive *pd;
|
|
Packit |
b1f7ae |
char *filename;
|
|
Packit |
b1f7ae |
FILE *f;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!p))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
pd = p->pd;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* the directive in the current line must be the .exp directive. */
|
|
Packit |
b1f7ae |
errcode = yasm_pd_parse(p->y, pd);
|
|
Packit |
b1f7ae |
if (bug_on(errcode < 0))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(strcmp(pd->name, ".exp") != 0))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
filename = expfilename(p, pd->payload);
|
|
Packit |
b1f7ae |
if (!filename)
|
|
Packit |
b1f7ae |
return -err_no_mem;
|
|
Packit |
b1f7ae |
f = fopen(filename, "w");
|
|
Packit |
b1f7ae |
if (!f) {
|
|
Packit |
b1f7ae |
free(filename);
|
|
Packit |
b1f7ae |
return -err_file_open;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
for (;;) {
|
|
Packit |
b1f7ae |
int i;
|
|
Packit |
b1f7ae |
char *line, *comment;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = yasm_next_line(p->y, s, slen);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = yasm_pd_parse(p->y, pd);
|
|
Packit |
b1f7ae |
if (errcode < 0 && errcode != -err_no_directive)
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (errcode == 0 && strcmp(pd->name, ".exp") == 0) {
|
|
Packit |
b1f7ae |
fclose(f);
|
|
Packit |
b1f7ae |
printf("%s\n", filename);
|
|
Packit |
b1f7ae |
free(filename);
|
|
Packit |
b1f7ae |
filename = expfilename(p, pd->payload);
|
|
Packit |
b1f7ae |
if (!filename)
|
|
Packit |
b1f7ae |
return -err_no_mem;
|
|
Packit |
b1f7ae |
f = fopen(filename, "w");
|
|
Packit |
b1f7ae |
if (!f) {
|
|
Packit |
b1f7ae |
free(filename);
|
|
Packit |
b1f7ae |
return -err_file_open;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
line = strchr(s, ';');
|
|
Packit |
b1f7ae |
if (!line)
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
line += 1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
comment = strchr(line, '#');
|
|
Packit |
b1f7ae |
if (comment)
|
|
Packit |
b1f7ae |
*comment = '\0';
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* remove trailing spaces. */
|
|
Packit |
b1f7ae |
for (i = (int) strlen(line)-1; i >= 0 && isspace(line[i]); i--)
|
|
Packit |
b1f7ae |
line[i] = '\0';
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
for (;;) {
|
|
Packit |
b1f7ae |
char *tmp, label[256];
|
|
Packit |
b1f7ae |
uint64_t addr;
|
|
Packit |
b1f7ae |
int zero_padding, qmark_padding, qmark_size, status;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
zero_padding = 0;
|
|
Packit |
b1f7ae |
qmark_padding = 0;
|
|
Packit |
b1f7ae |
qmark_size = 0;
|
|
Packit |
b1f7ae |
status = 0;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* find the label character in the string.
|
|
Packit |
b1f7ae |
* if there is no label character, we just print
|
|
Packit |
b1f7ae |
* the rest of the line and end.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
tmp = strchr(line, '%');
|
|
Packit |
b1f7ae |
if (!tmp) {
|
|
Packit |
b1f7ae |
if (fprintf(f, "%s", line) < 0) {
|
|
Packit |
b1f7ae |
errcode = -err_file_write;
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* make the label character a null byte and
|
|
Packit |
b1f7ae |
* print the first portion, which does not
|
|
Packit |
b1f7ae |
* belong to the label into the file.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
*tmp = '\0';
|
|
Packit |
b1f7ae |
if (fprintf(f, "%s", line) < 0) {
|
|
Packit |
b1f7ae |
errcode = -err_file_write;
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* test if there is a valid label name after the %. */
|
|
Packit |
b1f7ae |
line = tmp+1;
|
|
Packit |
b1f7ae |
if (*line == '\0' || isspace(*line)) {
|
|
Packit |
b1f7ae |
errcode = -err_no_label;
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* check if zero padding is requested. */
|
|
Packit |
b1f7ae |
if (*line == '0') {
|
|
Packit |
b1f7ae |
zero_padding = 1;
|
|
Packit |
b1f7ae |
line += 1;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
/* chek if ? padding is requested. */
|
|
Packit |
b1f7ae |
else if (*line == '?') {
|
|
Packit |
b1f7ae |
qmark_padding = 1;
|
|
Packit |
b1f7ae |
zero_padding = 1;
|
|
Packit |
b1f7ae |
qmark_size = 0;
|
|
Packit |
b1f7ae |
line += 1;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* advance i to the first non alpha-numeric
|
|
Packit |
b1f7ae |
* character. all characters everything from
|
|
Packit |
b1f7ae |
* line[0] to line[i-1] belongs to the label
|
|
Packit |
b1f7ae |
* name.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
for (i = 0; islabelchar(line[i]); i++)
|
|
Packit |
b1f7ae |
;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (i > 255) {
|
|
Packit |
b1f7ae |
errcode = -err_label_name;
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
strncpy(label, line, i);
|
|
Packit |
b1f7ae |
label[i] = '\0';
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* advance to next character. */
|
|
Packit |
b1f7ae |
line = &line[i];
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* lookup the label name and print it to the
|
|
Packit |
b1f7ae |
* output file.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
errcode = yasm_lookup_label(p->y, &addr, label);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
errcode = l_lookup(p->pt_labels, &addr, label);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (zero_padding)
|
|
Packit |
b1f7ae |
status = fprintf(f, "%016" PRIx64, addr);
|
|
Packit |
b1f7ae |
else
|
|
Packit |
b1f7ae |
status = fprintf(f, "%" PRIx64, addr);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (status < 0) {
|
|
Packit |
b1f7ae |
errcode = -err_file_write;
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* check if masking is requested. */
|
|
Packit |
b1f7ae |
if (*line == '.') {
|
|
Packit |
b1f7ae |
char *endptr;
|
|
Packit |
b1f7ae |
long int n;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
line += 1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
n = strtol(line, &endptr, 0);
|
|
Packit |
b1f7ae |
/* check if strtol made progress and
|
|
Packit |
b1f7ae |
* stops on a space or null byte.
|
|
Packit |
b1f7ae |
* otherwise the int could not be
|
|
Packit |
b1f7ae |
* parsed.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
if (line == endptr ||
|
|
Packit |
b1f7ae |
(*endptr != '\0' && !isspace(*endptr)
|
|
Packit |
b1f7ae |
&& !ispunct(*endptr))) {
|
|
Packit |
b1f7ae |
errcode = -err_parse_int;
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
addr &= (1ull << (n << 3)) - 1ull;
|
|
Packit |
b1f7ae |
line = endptr;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
qmark_size = 8 - n;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (qmark_padding) {
|
|
Packit |
b1f7ae |
for (i = 0; i < qmark_size; ++i) {
|
|
Packit |
b1f7ae |
status = fprintf(f, "??");
|
|
Packit |
b1f7ae |
if (status < 0) {
|
|
Packit |
b1f7ae |
errcode = -err_file_write;
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
for (; i < 8; ++i) {
|
|
Packit |
b1f7ae |
uint8_t byte;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
byte = (uint8_t)(addr >> ((7 - i) * 8));
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
status = fprintf(f, "%02" PRIx8, byte);
|
|
Packit |
b1f7ae |
if (status < 0) {
|
|
Packit |
b1f7ae |
errcode = -err_file_write;
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
} else if (zero_padding)
|
|
Packit |
b1f7ae |
status = fprintf(f, "%016" PRIx64, addr);
|
|
Packit |
b1f7ae |
else
|
|
Packit |
b1f7ae |
status = fprintf(f, "%" PRIx64, addr);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (status < 0) {
|
|
Packit |
b1f7ae |
errcode = -err_file_write;
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (fprintf(f, "\n") < 0) {
|
|
Packit |
b1f7ae |
errcode = -err_file_write;
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
error:
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
fclose(f);
|
|
Packit |
b1f7ae |
if (errcode < 0 && errcode != -err_out_of_range) {
|
|
Packit |
b1f7ae |
fprintf(stderr, "fatal: %s could not be created:\n", filename);
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "", errcode);
|
|
Packit |
b1f7ae |
remove(filename);
|
|
Packit |
b1f7ae |
} else
|
|
Packit |
b1f7ae |
printf("%s\n", filename);
|
|
Packit |
b1f7ae |
free(filename);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* If there are no lines left, we are done. */
|
|
Packit |
b1f7ae |
if (errcode == -err_out_of_range)
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static void p_close_files(struct parser *p)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (p->ptfile) {
|
|
Packit |
b1f7ae |
fclose(p->ptfile);
|
|
Packit |
b1f7ae |
p->ptfile = NULL;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static int p_open_files(struct parser *p)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
p->ptfile = fopen(p->ptfilename, "wb");
|
|
Packit |
b1f7ae |
if (!p->ptfile) {
|
|
Packit |
b1f7ae |
fprintf(stderr, "open %s failed\n", p->ptfilename);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
error:
|
|
Packit |
b1f7ae |
p_close_files(p);
|
|
Packit |
b1f7ae |
return -err_file_open;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Processes the current directive.
|
|
Packit |
b1f7ae |
* If the encoder returns an error, a message including current file and
|
|
Packit |
b1f7ae |
* line number together with the pt error string is printed on stderr.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns 0 on success; a negative enum errcode otherwise.
|
|
Packit |
b1f7ae |
* Returns -err_internal if @p or @e is the NULL pointer.
|
|
Packit |
b1f7ae |
* Returns -err_parse_missing_directive if there was a pt directive marker,
|
|
Packit |
b1f7ae |
* but no directive.
|
|
Packit |
b1f7ae |
* Returns -stop_process if the .exp directive was encountered.
|
|
Packit |
b1f7ae |
* Returns -err_pt_lib if the pt encoder returned an error.
|
|
Packit |
b1f7ae |
* Returns -err_parse if a general parsing error was encountered.
|
|
Packit |
b1f7ae |
* Returns -err_parse_unknown_directive if there was an unknown pt directive.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
static int p_process(struct parser *p, struct pt_encoder *e)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int bytes_written;
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
char *directive, *payload, *pt_label_name, *tmp;
|
|
Packit |
b1f7ae |
struct pt_directive *pd;
|
|
Packit |
b1f7ae |
struct pt_packet packet;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!p))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!e))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
pd = p->pd;
|
|
Packit |
b1f7ae |
if (!pd)
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
directive = pd->name;
|
|
Packit |
b1f7ae |
payload = pd->payload;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
pt_label_name = NULL;
|
|
Packit |
b1f7ae |
bytes_written = 0;
|
|
Packit |
b1f7ae |
errcode = 0;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* find a label name. */
|
|
Packit |
b1f7ae |
tmp = strchr(directive, ':');
|
|
Packit |
b1f7ae |
if (tmp) {
|
|
Packit |
b1f7ae |
uint64_t x;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
pt_label_name = directive;
|
|
Packit |
b1f7ae |
directive = tmp+1;
|
|
Packit |
b1f7ae |
*tmp = '\0';
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* ignore whitespace between label and directive. */
|
|
Packit |
b1f7ae |
while (isspace(*directive))
|
|
Packit |
b1f7ae |
directive += 1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* if we can lookup a yasm label with the same name, the
|
|
Packit |
b1f7ae |
* current pt directive label is invalid. */
|
|
Packit |
b1f7ae |
errcode = yasm_lookup_label(p->y, &x, pt_label_name);
|
|
Packit |
b1f7ae |
if (errcode == 0)
|
|
Packit |
b1f7ae |
errcode = -err_label_not_unique;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (errcode != -err_no_label)
|
|
Packit |
b1f7ae |
return yasm_print_err(p->y, "label lookup",
|
|
Packit |
b1f7ae |
errcode);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* if we can lookup a pt directive label with the same
|
|
Packit |
b1f7ae |
* name, the current pt directive label is invalid. */
|
|
Packit |
b1f7ae |
errcode = l_lookup(p->pt_labels, &x, pt_label_name);
|
|
Packit |
b1f7ae |
if (errcode == 0)
|
|
Packit |
b1f7ae |
errcode = -err_label_not_unique;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (errcode != -err_no_label)
|
|
Packit |
b1f7ae |
return yasm_print_err(p->y, "label lookup",
|
|
Packit |
b1f7ae |
-err_label_not_unique);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* now try to match the directive string and call the
|
|
Packit |
b1f7ae |
* corresponding function that parses the payload and emits an
|
|
Packit |
b1f7ae |
* according packet.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
if (strcmp(directive, "") == 0)
|
|
Packit |
b1f7ae |
return yasm_print_err(p->y, "invalid syntax",
|
|
Packit |
b1f7ae |
-err_parse_missing_directive);
|
|
Packit |
b1f7ae |
else if (strcmp(directive, ".exp") == 0) {
|
|
Packit |
b1f7ae |
/* this is the end of processing pt directives, so we
|
|
Packit |
b1f7ae |
* add a p_last label to the pt directive labels.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
errcode = l_append(p->pt_labels, "eos", p->pt_bytes_written);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return yasm_print_err(p->y, "append label", errcode);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return -stop_process;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (strcmp(directive, "psb") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_empty(payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "psb: parsing failed", errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_psb;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "psbend") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_empty(payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "psbend: parsing failed", errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_psbend;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "pad") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_empty(payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "pad: parsing failed", errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_pad;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "ovf") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_empty(payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "ovf: parsing failed", errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_ovf;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "stop") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_empty(payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "stop: parsing failed", errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_stop;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "tnt") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_tnt(&packet.payload.tnt.payload,
|
|
Packit |
b1f7ae |
&packet.payload.tnt.bit_size, payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "tnt: parsing failed", errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_tnt_8;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "tnt64") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_tnt(&packet.payload.tnt.payload,
|
|
Packit |
b1f7ae |
&packet.payload.tnt.bit_size, payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "tnt64: parsing failed", errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_tnt_64;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "tip") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_ip(p, &packet.payload.ip.ip,
|
|
Packit |
b1f7ae |
&packet.payload.ip.ipc, payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "tip: parsing failed", errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_tip;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "tip.pge") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_ip(p, &packet.payload.ip.ip,
|
|
Packit |
b1f7ae |
&packet.payload.ip.ipc, payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "tip.pge: parsing failed",
|
|
Packit |
b1f7ae |
errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_tip_pge;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "tip.pgd") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_ip(p, &packet.payload.ip.ip,
|
|
Packit |
b1f7ae |
&packet.payload.ip.ipc, payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "tip.pgd: parsing failed",
|
|
Packit |
b1f7ae |
errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_tip_pgd;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "fup") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_ip(p, &packet.payload.ip.ip,
|
|
Packit |
b1f7ae |
&packet.payload.ip.ipc, payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "fup: parsing failed", errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_fup;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "mode.exec") == 0) {
|
|
Packit |
b1f7ae |
if (strcmp(payload, "16bit") == 0) {
|
|
Packit |
b1f7ae |
packet.payload.mode.bits.exec.csl = 0;
|
|
Packit |
b1f7ae |
packet.payload.mode.bits.exec.csd = 0;
|
|
Packit |
b1f7ae |
} else if (strcmp(payload, "64bit") == 0) {
|
|
Packit |
b1f7ae |
packet.payload.mode.bits.exec.csl = 1;
|
|
Packit |
b1f7ae |
packet.payload.mode.bits.exec.csd = 0;
|
|
Packit |
b1f7ae |
} else if (strcmp(payload, "32bit") == 0) {
|
|
Packit |
b1f7ae |
packet.payload.mode.bits.exec.csl = 0;
|
|
Packit |
b1f7ae |
packet.payload.mode.bits.exec.csd = 1;
|
|
Packit |
b1f7ae |
} else {
|
|
Packit |
b1f7ae |
errcode = yasm_print_err(p->y,
|
|
Packit |
b1f7ae |
"mode.exec: argument must be one of \"16bit\", \"64bit\" or \"32bit\"",
|
|
Packit |
b1f7ae |
-err_parse);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.payload.mode.leaf = pt_mol_exec;
|
|
Packit |
b1f7ae |
packet.type = ppt_mode;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "mode.tsx") == 0) {
|
|
Packit |
b1f7ae |
if (strcmp(payload, "begin") == 0) {
|
|
Packit |
b1f7ae |
packet.payload.mode.bits.tsx.intx = 1;
|
|
Packit |
b1f7ae |
packet.payload.mode.bits.tsx.abrt = 0;
|
|
Packit |
b1f7ae |
} else if (strcmp(payload, "abort") == 0) {
|
|
Packit |
b1f7ae |
packet.payload.mode.bits.tsx.intx = 0;
|
|
Packit |
b1f7ae |
packet.payload.mode.bits.tsx.abrt = 1;
|
|
Packit |
b1f7ae |
} else if (strcmp(payload, "commit") == 0) {
|
|
Packit |
b1f7ae |
packet.payload.mode.bits.tsx.intx = 0;
|
|
Packit |
b1f7ae |
packet.payload.mode.bits.tsx.abrt = 0;
|
|
Packit |
b1f7ae |
} else {
|
|
Packit |
b1f7ae |
errcode = yasm_print_err(p->y,
|
|
Packit |
b1f7ae |
"mode.tsx: argument must be one of \"begin\", \"abort\" or \"commit\"",
|
|
Packit |
b1f7ae |
-err_parse);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.payload.mode.leaf = pt_mol_tsx;
|
|
Packit |
b1f7ae |
packet.type = ppt_mode;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "pip") == 0) {
|
|
Packit |
b1f7ae |
const char *modifier;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = parse_uint64(&packet.payload.pip.cr3, payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "pip: parsing failed", errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_pip;
|
|
Packit |
b1f7ae |
packet.payload.pip.nr = 0;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
modifier = strtok(NULL, " ,");
|
|
Packit |
b1f7ae |
if (modifier) {
|
|
Packit |
b1f7ae |
if (strcmp(modifier, "nr") == 0)
|
|
Packit |
b1f7ae |
packet.payload.pip.nr = 1;
|
|
Packit |
b1f7ae |
else {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "pip: parsing failed",
|
|
Packit |
b1f7ae |
-err_parse_trailing_tokens);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "tsc") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_uint64(&packet.payload.tsc.tsc, payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "tsc: parsing failed", errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_tsc;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "cbr") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_uint8(&packet.payload.cbr.ratio, payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "cbr: parsing cbr failed",
|
|
Packit |
b1f7ae |
errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_cbr;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "tma") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_tma(&packet.payload.tma.ctc,
|
|
Packit |
b1f7ae |
&packet.payload.tma.fc, payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "tma: parsing tma failed",
|
|
Packit |
b1f7ae |
errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_tma;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "mtc") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_uint8(&packet.payload.mtc.ctc, payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "mtc: parsing mtc failed",
|
|
Packit |
b1f7ae |
errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_mtc;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "cyc") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_uint64(&packet.payload.cyc.value, payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "cyc: parsing cyc failed",
|
|
Packit |
b1f7ae |
errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_cyc;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "vmcs") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_uint64(&packet.payload.vmcs.base, payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "vmcs: parsing failed", errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_vmcs;
|
|
Packit |
b1f7ae |
} else if (strcmp(directive, "mnt") == 0) {
|
|
Packit |
b1f7ae |
errcode = parse_uint64(&packet.payload.mnt.payload, payload);
|
|
Packit |
b1f7ae |
if (errcode < 0) {
|
|
Packit |
b1f7ae |
yasm_print_err(p->y, "mnt: parsing failed", errcode);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
packet.type = ppt_mnt;
|
|
Packit |
b1f7ae |
} else {
|
|
Packit |
b1f7ae |
errcode = yasm_print_err(p->y, "invalid syntax",
|
|
Packit |
b1f7ae |
-err_parse_unknown_directive);
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
bytes_written = pt_enc_next(e, &packet);
|
|
Packit |
b1f7ae |
if (bytes_written < 0) {
|
|
Packit |
b1f7ae |
const char *errtext, *format;
|
|
Packit |
b1f7ae |
char *msg;
|
|
Packit |
b1f7ae |
size_t n;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errtext = pt_errstr(pt_errcode(bytes_written));
|
|
Packit |
b1f7ae |
format = "encoder error in directive %s (status %s)";
|
|
Packit |
b1f7ae |
/* the length of format includes the "%s" (-2)
|
|
Packit |
b1f7ae |
* characters, we add errtext (+-0) and then we need
|
|
Packit |
b1f7ae |
* space for a terminating null-byte (+1).
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
n = strlen(format)-4 + strlen(directive) + strlen(errtext) + 1;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
msg = malloc(n);
|
|
Packit |
b1f7ae |
if (!msg)
|
|
Packit |
b1f7ae |
errcode = yasm_print_err(p->y,
|
|
Packit |
b1f7ae |
"encoder error not enough memory to show error code",
|
|
Packit |
b1f7ae |
-err_pt_lib);
|
|
Packit |
b1f7ae |
else {
|
|
Packit |
b1f7ae |
sprintf(msg, format, directive, errtext);
|
|
Packit |
b1f7ae |
errcode = yasm_print_err(p->y, msg, -err_pt_lib);
|
|
Packit |
b1f7ae |
free(msg);
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
} else {
|
|
Packit |
b1f7ae |
if (pt_label_name) {
|
|
Packit |
b1f7ae |
errcode = l_append(p->pt_labels, pt_label_name,
|
|
Packit |
b1f7ae |
p->pt_bytes_written);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
p->pt_bytes_written += bytes_written;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
error:
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
bytes_written = errcode;
|
|
Packit |
b1f7ae |
return bytes_written;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* Starts the parsing process.
|
|
Packit |
b1f7ae |
*
|
|
Packit |
b1f7ae |
* Returns 0 on success; a negative enum errcode otherwise.
|
|
Packit |
b1f7ae |
* Returns -err_pt_lib if the pt encoder could not be initialized.
|
|
Packit |
b1f7ae |
* Returns -err_file_write if the .pt or .exp file could not be fully
|
|
Packit |
b1f7ae |
* written.
|
|
Packit |
b1f7ae |
*/
|
|
Packit |
b1f7ae |
int p_start(struct parser *p)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!p))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = yasm_parse(p->y);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
for (;;) {
|
|
Packit |
b1f7ae |
int bytes_written;
|
|
Packit |
b1f7ae |
struct pt_encoder *e;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = yasm_next_pt_directive(p->y, p->pd);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
e = pt_alloc_encoder(p->conf);
|
|
Packit |
b1f7ae |
if (!e) {
|
|
Packit |
b1f7ae |
fprintf(stderr, "pt_alloc_encoder failed\n");
|
|
Packit |
b1f7ae |
errcode = -err_pt_lib;
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
bytes_written = p_process(p, e);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
pt_free_encoder(e);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bytes_written == -stop_process) {
|
|
Packit |
b1f7ae |
errcode = p_gen_expfile(p);
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
if (bytes_written < 0) {
|
|
Packit |
b1f7ae |
errcode = bytes_written;
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
if (fwrite(p->conf->begin, 1, bytes_written, p->ptfile)
|
|
Packit |
b1f7ae |
!= (size_t)bytes_written) {
|
|
Packit |
b1f7ae |
fprintf(stderr, "write %s failed", p->ptfilename);
|
|
Packit |
b1f7ae |
errcode = -err_file_write;
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* If there is no directive left, there's nothing more to do. */
|
|
Packit |
b1f7ae |
if (errcode == -err_no_directive)
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int parse(const char *pttfile, const struct pt_config *conf)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
struct parser *p;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
p = p_alloc(pttfile, conf);
|
|
Packit |
b1f7ae |
if (!p)
|
|
Packit |
b1f7ae |
return -err_no_mem;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = p_open_files(p);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
goto error;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = p_start(p);
|
|
Packit |
b1f7ae |
p_close_files(p);
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
error:
|
|
Packit |
b1f7ae |
p_free(p);
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int parse_empty(char *payload)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
if (!payload)
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
strtok(payload, " ");
|
|
Packit |
b1f7ae |
if (!payload || *payload == '\0')
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return -err_parse_trailing_tokens;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int parse_tnt(uint64_t *tnt, uint8_t *size, char *payload)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
char c;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!size))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!tnt))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
*size = 0;
|
|
Packit |
b1f7ae |
*tnt = 0ull;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (!payload)
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
while (*payload != '\0') {
|
|
Packit |
b1f7ae |
c = *payload;
|
|
Packit |
b1f7ae |
payload++;
|
|
Packit |
b1f7ae |
if (isspace(c) || c == '.')
|
|
Packit |
b1f7ae |
continue;
|
|
Packit |
b1f7ae |
*size += 1;
|
|
Packit |
b1f7ae |
*tnt <<= 1;
|
|
Packit |
b1f7ae |
switch (c) {
|
|
Packit |
b1f7ae |
case 'n':
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
case 't':
|
|
Packit |
b1f7ae |
*tnt |= 1;
|
|
Packit |
b1f7ae |
break;
|
|
Packit |
b1f7ae |
default:
|
|
Packit |
b1f7ae |
return -err_parse_unknown_char;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
static int check_ipc(enum pt_ip_compression ipc)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
switch (ipc) {
|
|
Packit |
b1f7ae |
case pt_ipc_suppressed:
|
|
Packit |
b1f7ae |
case pt_ipc_update_16:
|
|
Packit |
b1f7ae |
case pt_ipc_update_32:
|
|
Packit |
b1f7ae |
case pt_ipc_update_48:
|
|
Packit |
b1f7ae |
case pt_ipc_sext_48:
|
|
Packit |
b1f7ae |
case pt_ipc_full:
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
return -err_parse_ipc;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int parse_ip(struct parser *p, uint64_t *ip, enum pt_ip_compression *ipc,
|
|
Packit |
b1f7ae |
char *payload)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
char *endptr;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!ip))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!ipc))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
*ipc = pt_ipc_suppressed;
|
|
Packit |
b1f7ae |
*ip = 0;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
payload = strtok(payload, " :");
|
|
Packit |
b1f7ae |
if (!payload || *payload == '\0')
|
|
Packit |
b1f7ae |
return -err_parse_no_args;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
*ipc = (enum pt_ip_compression) strtol(payload, &endptr, 0);
|
|
Packit |
b1f7ae |
if (payload == endptr || *endptr != '\0')
|
|
Packit |
b1f7ae |
return -err_parse_ipc;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* is ipc valid? */
|
|
Packit |
b1f7ae |
errcode = check_ipc(*ipc);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
payload = strtok(NULL, " :");
|
|
Packit |
b1f7ae |
if (!payload)
|
|
Packit |
b1f7ae |
return -err_parse_ip_missing;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* can be resolved to a label? */
|
|
Packit |
b1f7ae |
if (*payload == '%') {
|
|
Packit |
b1f7ae |
if (!p)
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = yasm_lookup_label(p->y, ip, payload + 1);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
} else {
|
|
Packit |
b1f7ae |
/* can be parsed as address? */
|
|
Packit |
b1f7ae |
errcode = str_to_uint64(payload, ip, 0);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* no more tokens left. */
|
|
Packit |
b1f7ae |
payload = strtok(NULL, " ");
|
|
Packit |
b1f7ae |
if (payload)
|
|
Packit |
b1f7ae |
return -err_parse_trailing_tokens;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int parse_uint64(uint64_t *x, char *payload)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!x))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
payload = strtok(payload, " ,");
|
|
Packit |
b1f7ae |
if (!payload)
|
|
Packit |
b1f7ae |
return -err_parse_no_args;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = str_to_uint64(payload, x, 0);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int parse_uint32(uint32_t *x, char *payload)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!x))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
payload = strtok(payload, " ,");
|
|
Packit |
b1f7ae |
if (!payload)
|
|
Packit |
b1f7ae |
return -err_parse_no_args;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = str_to_uint32(payload, x, 0);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int parse_uint16(uint16_t *x, char *payload)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!x))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
payload = strtok(payload, " ,");
|
|
Packit |
b1f7ae |
if (!payload)
|
|
Packit |
b1f7ae |
return -err_parse_no_args;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = str_to_uint16(payload, x, 0);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int parse_uint8(uint8_t *x, char *payload)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
int errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!x))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
payload = strtok(payload, " ,");
|
|
Packit |
b1f7ae |
if (!payload)
|
|
Packit |
b1f7ae |
return -err_parse_no_args;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
errcode = str_to_uint8(payload, x, 0);
|
|
Packit |
b1f7ae |
if (errcode < 0)
|
|
Packit |
b1f7ae |
return errcode;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
int parse_tma(uint16_t *ctc, uint16_t *fc, char *payload)
|
|
Packit |
b1f7ae |
{
|
|
Packit |
b1f7ae |
char *endptr;
|
|
Packit |
b1f7ae |
long int i;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (bug_on(!ctc || !fc))
|
|
Packit |
b1f7ae |
return -err_internal;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
payload = strtok(payload, ",");
|
|
Packit |
b1f7ae |
if (!payload || *payload == '\0')
|
|
Packit |
b1f7ae |
return -err_parse_no_args;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
i = strtol(payload, &endptr, 0);
|
|
Packit |
b1f7ae |
if (payload == endptr || *endptr != '\0')
|
|
Packit |
b1f7ae |
return -err_parse_int;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (i > 0xffffl)
|
|
Packit |
b1f7ae |
return -err_parse_int_too_big;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
*ctc = (uint16_t)i;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
payload = strtok(NULL, " ,");
|
|
Packit |
b1f7ae |
if (!payload)
|
|
Packit |
b1f7ae |
return -err_parse_no_args;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
i = strtol(payload, &endptr, 0);
|
|
Packit |
b1f7ae |
if (payload == endptr || *endptr != '\0')
|
|
Packit |
b1f7ae |
return -err_parse_int;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
if (i > 0xffffl)
|
|
Packit |
b1f7ae |
return -err_parse_int_too_big;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
*fc = (uint16_t)i;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
/* no more tokens left. */
|
|
Packit |
b1f7ae |
payload = strtok(NULL, " ");
|
|
Packit |
b1f7ae |
if (payload)
|
|
Packit |
b1f7ae |
return -err_parse_trailing_tokens;
|
|
Packit |
b1f7ae |
|
|
Packit |
b1f7ae |
return 0;
|
|
Packit |
b1f7ae |
}
|