mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-09-22 10:43:39 -04:00
Sanitize the handling of messsages; improve info and debug
Make the handling of messages saner. In particular, regularize the handling of info and debug messages, so that nasm_info() and nasm_debug() actually become useful. Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
85
asm/error.c
85
asm/error.c
@@ -1,6 +1,6 @@
|
|||||||
/* ----------------------------------------------------------------------- *
|
/* ----------------------------------------------------------------------- *
|
||||||
*
|
*
|
||||||
* Copyright 1996-2024 The NASM Authors - All Rights Reserved
|
* Copyright 1996-2025 The NASM Authors - All Rights Reserved
|
||||||
* See the file AUTHORS included with the NASM distribution for
|
* See the file AUTHORS included with the NASM distribution for
|
||||||
* the specific copyright holders.
|
* the specific copyright holders.
|
||||||
*
|
*
|
||||||
@@ -36,27 +36,34 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
|
|
||||||
|
|
||||||
#include "nasmlib.h"
|
#include "nasmlib.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
|
unsigned int debug_nasm; /* Debugging messages? */
|
||||||
|
unsigned int opt_verbose_info; /* Informational messages? */
|
||||||
|
|
||||||
/* Common function body */
|
/* Common function body */
|
||||||
#define nasm_do_error(_sev,_flags) \
|
#define nasm_do_error(_sev,_flags) \
|
||||||
va_list ap; \
|
do { \
|
||||||
va_start(ap, fmt); \
|
va_list ap; \
|
||||||
if ((_sev) >= ERR_CRITICAL) \
|
va_start(ap, fmt); \
|
||||||
nasm_verror_critical((_sev)|(_flags), fmt, ap); \
|
if ((_sev) >= ERR_CRITICAL) \
|
||||||
else \
|
nasm_verror_critical((_sev)|(_flags), fmt, ap); \
|
||||||
nasm_verror((_sev)|(_flags), fmt, ap); \
|
else \
|
||||||
va_end(ap); \
|
nasm_verror((_sev)|(_flags), fmt, ap); \
|
||||||
if ((_sev) >= ERR_FATAL) \
|
va_end(ap); \
|
||||||
abort();
|
if ((_sev) >= ERR_FATAL) \
|
||||||
|
abort(); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
void nasm_error(errflags severity, const char *fmt, ...)
|
* This is the generic function to use when the error type is not
|
||||||
|
* known a priori. For ERR_DEBUG and ERR_INFO the level can be
|
||||||
|
* included by
|
||||||
|
*/
|
||||||
|
void nasm_error(errflags flags, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
nasm_do_error(severity & ERR_MASK, severity & ~ERR_MASK);
|
nasm_do_error(flags & ERR_MASK, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define nasm_err_helpers(_type, _name, _sev) \
|
#define nasm_err_helpers(_type, _name, _sev) \
|
||||||
@@ -71,8 +78,6 @@ _type nasm_ ## _name (const char *fmt, ...) \
|
|||||||
|
|
||||||
nasm_err_helpers(void, listmsg, ERR_LISTMSG)
|
nasm_err_helpers(void, listmsg, ERR_LISTMSG)
|
||||||
nasm_err_helpers(void, note, ERR_NOTE)
|
nasm_err_helpers(void, note, ERR_NOTE)
|
||||||
nasm_err_helpers(void, debug, ERR_DEBUG)
|
|
||||||
nasm_err_helpers(void, info, ERR_INFO)
|
|
||||||
nasm_err_helpers(void, nonfatal, ERR_NONFATAL)
|
nasm_err_helpers(void, nonfatal, ERR_NONFATAL)
|
||||||
nasm_err_helpers(fatal_func, fatal, ERR_FATAL)
|
nasm_err_helpers(fatal_func, fatal, ERR_FATAL)
|
||||||
nasm_err_helpers(fatal_func, critical, ERR_CRITICAL)
|
nasm_err_helpers(fatal_func, critical, ERR_CRITICAL)
|
||||||
@@ -88,7 +93,22 @@ nasm_err_helpers(fatal_func, panic, ERR_PANIC)
|
|||||||
*/
|
*/
|
||||||
void nasm_warn_(errflags flags, const char *fmt, ...)
|
void nasm_warn_(errflags flags, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
nasm_do_error(ERR_WARNING, flags);
|
nasm_do_error(ERR_WARNING, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nasm_info() and nasm_debug() takes mandatory enabling levels.
|
||||||
|
*/
|
||||||
|
void nasm_info_(unsigned int level, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
if (info_level(level))
|
||||||
|
nasm_do_error(ERR_INFO, LEVEL(level));
|
||||||
|
}
|
||||||
|
|
||||||
|
void nasm_debug_(unsigned int level, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
if (debug_level(level))
|
||||||
|
nasm_do_error(ERR_DEBUG, LEVEL(level));
|
||||||
}
|
}
|
||||||
|
|
||||||
fatal_func nasm_panic_from_macro(const char *func, const char *file, int line)
|
fatal_func nasm_panic_from_macro(const char *func, const char *file, int line)
|
||||||
@@ -297,3 +317,32 @@ bool set_warning_status(const char *value)
|
|||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The various error type prefixes
|
||||||
|
*/
|
||||||
|
const char *error_pfx(errflags severity)
|
||||||
|
{
|
||||||
|
switch (severity & ERR_MASK) {
|
||||||
|
case ERR_LISTMSG:
|
||||||
|
return ";;; ";
|
||||||
|
case ERR_NOTE:
|
||||||
|
return "note: ";
|
||||||
|
case ERR_DEBUG:
|
||||||
|
return "debug: ";
|
||||||
|
case ERR_INFO:
|
||||||
|
return "info: ";
|
||||||
|
case ERR_WARNING:
|
||||||
|
return "warning: ";
|
||||||
|
case ERR_NONFATAL:
|
||||||
|
return "error: ";
|
||||||
|
case ERR_FATAL:
|
||||||
|
return "fatal: ";
|
||||||
|
case ERR_CRITICAL:
|
||||||
|
return "critical: ";
|
||||||
|
case ERR_PANIC:
|
||||||
|
return "panic: ";
|
||||||
|
default:
|
||||||
|
return "internal error: ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
163
asm/nasm.c
163
asm/nasm.c
@@ -90,9 +90,7 @@ static const struct error_format *errfmt = &errfmt_gnu;
|
|||||||
static struct strlist *warn_list;
|
static struct strlist *warn_list;
|
||||||
static struct nasm_errhold *errhold_stack;
|
static struct nasm_errhold *errhold_stack;
|
||||||
|
|
||||||
unsigned int debug_nasm; /* Debugging messages? */
|
static bool using_debug_info;
|
||||||
|
|
||||||
static bool using_debug_info, opt_verbose_info;
|
|
||||||
static const char *debug_format;
|
static const char *debug_format;
|
||||||
|
|
||||||
#ifndef ABORT_ON_PANIC
|
#ifndef ABORT_ON_PANIC
|
||||||
@@ -122,7 +120,8 @@ const struct ofmt *ofmt = &OF_DEFAULT;
|
|||||||
const struct ofmt_alias *ofmt_alias = NULL;
|
const struct ofmt_alias *ofmt_alias = NULL;
|
||||||
const struct dfmt *dfmt;
|
const struct dfmt *dfmt;
|
||||||
|
|
||||||
FILE *error_file; /* Where to write error messages */
|
static FILE *error_file; /* Where to write error messages */
|
||||||
|
errflags errflags_never = 0; /* Error flags to unconditionally suppress */
|
||||||
|
|
||||||
FILE *ofile = NULL;
|
FILE *ofile = NULL;
|
||||||
enum optimization optimizing = OPTIM_DEFAULT;
|
enum optimization optimizing = OPTIM_DEFAULT;
|
||||||
@@ -942,6 +941,7 @@ enum text_options {
|
|||||||
OPT_KEEP_ALL,
|
OPT_KEEP_ALL,
|
||||||
OPT_NO_LINE,
|
OPT_NO_LINE,
|
||||||
OPT_DEBUG,
|
OPT_DEBUG,
|
||||||
|
OPT_INFO,
|
||||||
OPT_REPRODUCIBLE
|
OPT_REPRODUCIBLE
|
||||||
};
|
};
|
||||||
enum need_arg {
|
enum need_arg {
|
||||||
@@ -973,6 +973,8 @@ static const struct textargs textopts[] = {
|
|||||||
{"limit-", OPT_LIMIT, ARG_YES, 0},
|
{"limit-", OPT_LIMIT, ARG_YES, 0},
|
||||||
{"keep-all", OPT_KEEP_ALL, ARG_NO, 0},
|
{"keep-all", OPT_KEEP_ALL, ARG_NO, 0},
|
||||||
{"no-line", OPT_NO_LINE, ARG_NO, 0},
|
{"no-line", OPT_NO_LINE, ARG_NO, 0},
|
||||||
|
{"info", OPT_INFO , ARG_MAYBE, 0},
|
||||||
|
{"verbose", OPT_INFO , ARG_MAYBE, 0},
|
||||||
{"debug", OPT_DEBUG, ARG_MAYBE, 0},
|
{"debug", OPT_DEBUG, ARG_MAYBE, 0},
|
||||||
{"reproducible", OPT_REPRODUCIBLE, ARG_NO, 0},
|
{"reproducible", OPT_REPRODUCIBLE, ARG_NO, 0},
|
||||||
{NULL, OPT_BOGUS, ARG_NO, 0}
|
{NULL, OPT_BOGUS, ARG_NO, 0}
|
||||||
@@ -1050,7 +1052,7 @@ static bool process_arg(char *p, char *q, int pass)
|
|||||||
case 'v':
|
case 'v':
|
||||||
case '+':
|
case '+':
|
||||||
param++;
|
param++;
|
||||||
opt_verbose_info = true;
|
opt_verbose_info++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
@@ -1341,8 +1343,14 @@ static bool process_arg(char *p, char *q, int pass)
|
|||||||
ppopt |= PP_NOLINE;
|
ppopt |= PP_NOLINE;
|
||||||
break;
|
break;
|
||||||
case OPT_DEBUG:
|
case OPT_DEBUG:
|
||||||
debug_nasm = param ?
|
if (pass == 1)
|
||||||
strtoul(param, NULL, 10) : debug_nasm+1;
|
debug_nasm = param ?
|
||||||
|
strtoul(param, NULL, 10) : debug_nasm+1;
|
||||||
|
break;
|
||||||
|
case OPT_INFO:
|
||||||
|
if (pass == 1)
|
||||||
|
opt_verbose_info = param ?
|
||||||
|
strtoul(param, NULL, 10) : opt_verbose_info+1;
|
||||||
break;
|
break;
|
||||||
case OPT_REPRODUCIBLE:
|
case OPT_REPRODUCIBLE:
|
||||||
reproducible = true;
|
reproducible = true;
|
||||||
@@ -1647,6 +1655,11 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
|
|||||||
if (!pass_final() && !warn_list)
|
if (!pass_final() && !warn_list)
|
||||||
warn_list = strlist_alloc(false);
|
warn_list = strlist_alloc(false);
|
||||||
|
|
||||||
|
/* Suppress ERR_PASS2 unless we are actually in the final pass */
|
||||||
|
errflags_never = 0;
|
||||||
|
if (!pass_final())
|
||||||
|
errflags_never |= ERR_PASS2;
|
||||||
|
|
||||||
globl.bits = cmd_sb; /* set 'bits' to command line default */
|
globl.bits = cmd_sb; /* set 'bits' to command line default */
|
||||||
globl.bnd = false;
|
globl.bnd = false;
|
||||||
globl.rel = false;
|
globl.rel = false;
|
||||||
@@ -1767,34 +1780,15 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
|
|||||||
reset_warnings();
|
reset_warnings();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt_verbose_info && pass_final()) {
|
if (pass_final()) {
|
||||||
/* -On and -Ov switches */
|
/* -On and -Ov switches */
|
||||||
nasm_info("assembly required 1+%"PRId64"+2 passes\n", pass_count()-3);
|
nasm_info(1, "assembly required 1+%"PRId64"+2 passes\n", pass_count()-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
lfmt->cleanup();
|
lfmt->cleanup();
|
||||||
strlist_free(&warn_list);
|
strlist_free(&warn_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* get warning index; 0 if this is non-suppressible.
|
|
||||||
*/
|
|
||||||
static size_t pure_func warn_index(errflags severity)
|
|
||||||
{
|
|
||||||
size_t index;
|
|
||||||
|
|
||||||
if ((severity & ERR_MASK) >= ERR_FATAL)
|
|
||||||
return 0; /* Fatal errors are never suppressible */
|
|
||||||
|
|
||||||
/* Warnings MUST HAVE a warning category specifier! */
|
|
||||||
nasm_assert((severity & (ERR_MASK|WARN_MASK)) != ERR_WARNING);
|
|
||||||
|
|
||||||
index = WARN_IDX(severity);
|
|
||||||
nasm_assert(index < WARN_IDX_ALL);
|
|
||||||
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool skip_this_pass(errflags severity)
|
static bool skip_this_pass(errflags severity)
|
||||||
{
|
{
|
||||||
errflags type = severity & ERR_MASK;
|
errflags type = severity & ERR_MASK;
|
||||||
@@ -1830,21 +1824,42 @@ static bool skip_this_pass(errflags severity)
|
|||||||
* @param severity the severity of the warning or error
|
* @param severity the severity of the warning or error
|
||||||
* @return true if we should abort error/warning printing
|
* @return true if we should abort error/warning printing
|
||||||
*/
|
*/
|
||||||
static bool is_suppressed(errflags severity)
|
static bool is_suppressed(errflags flags)
|
||||||
{
|
{
|
||||||
/* Fatal errors must never be suppressed */
|
const errflags severity = flags & ERR_MASK;
|
||||||
if ((severity & ERR_MASK) >= ERR_FATAL)
|
const errflags level = WARN_IDX(flags);
|
||||||
|
|
||||||
|
if (severity >= ERR_FATAL) {
|
||||||
|
/* Fatal errors or higher can never be suppressed */
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* This error/warning is pointless if we are dead anyway */
|
if (flags & errflags_never)
|
||||||
if ((severity & ERR_UNDEAD) && terminate_after_phase)
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!(warning_state[warn_index(severity)] & WARN_ST_ENABLED))
|
switch (severity) {
|
||||||
return true;
|
case ERR_WARNING:
|
||||||
|
if (!(warning_state[level] & WARN_ST_ENABLED))
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
|
||||||
if (!(severity & ERR_PP_LISTMACRO))
|
case ERR_INFO:
|
||||||
return pp_suppress_error(severity);
|
if (!info_level(level))
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ERR_DEBUG:
|
||||||
|
if (!debug_level(level))
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Suppressed by the preprocessor? */
|
||||||
|
if (!(flags & ERR_PP_LISTMACRO))
|
||||||
|
return pp_suppress_error(flags);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1866,7 +1881,7 @@ static errflags pure_func true_error_type(errflags severity)
|
|||||||
|
|
||||||
/* Promote warning to error? */
|
/* Promote warning to error? */
|
||||||
if (type == ERR_WARNING) {
|
if (type == ERR_WARNING) {
|
||||||
uint8_t state = warning_state[warn_index(severity)];
|
uint8_t state = warning_state[WARN_IDX(severity)];
|
||||||
if ((state & warn_is_err) == warn_is_err)
|
if ((state & warn_is_err) == warn_is_err)
|
||||||
type = ERR_NONFATAL;
|
type = ERR_NONFATAL;
|
||||||
}
|
}
|
||||||
@@ -1874,37 +1889,6 @@ static errflags pure_func true_error_type(errflags severity)
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* The various error type prefixes
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* The various error type prefixes
|
|
||||||
*/
|
|
||||||
static inline const char *error_pfx(errflags severity)
|
|
||||||
{
|
|
||||||
switch (severity & ERR_MASK) {
|
|
||||||
case ERR_LISTMSG:
|
|
||||||
return ";;; ";
|
|
||||||
case ERR_NOTE:
|
|
||||||
return "note: ";
|
|
||||||
case ERR_DEBUG:
|
|
||||||
return "debug: ";
|
|
||||||
case ERR_INFO:
|
|
||||||
return "info: ";
|
|
||||||
case ERR_WARNING:
|
|
||||||
return "warning: ";
|
|
||||||
case ERR_NONFATAL:
|
|
||||||
return "error: ";
|
|
||||||
case ERR_FATAL:
|
|
||||||
return "fatal: ";
|
|
||||||
case ERR_CRITICAL:
|
|
||||||
return "critical: ";
|
|
||||||
case ERR_PANIC:
|
|
||||||
return "panic: ";
|
|
||||||
default:
|
|
||||||
return "internal error: ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static const char no_file_name[] = "nasm"; /* What to print if no file name */
|
static const char no_file_name[] = "nasm"; /* What to print if no file name */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2084,8 +2068,10 @@ void nasm_verror(errflags severity, const char *fmt, va_list args)
|
|||||||
struct nasm_errtext *et;
|
struct nasm_errtext *et;
|
||||||
errflags true_type = true_error_type(severity);
|
errflags true_type = true_error_type(severity);
|
||||||
|
|
||||||
if (true_type >= ERR_CRITICAL)
|
if (true_type >= ERR_CRITICAL) {
|
||||||
nasm_verror_critical(severity, fmt, args);
|
nasm_verror_critical(severity, fmt, args);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
if (is_suppressed(severity))
|
if (is_suppressed(severity))
|
||||||
return;
|
return;
|
||||||
@@ -2133,14 +2119,25 @@ static void nasm_issue_error(struct nasm_errtext *et)
|
|||||||
pfx = error_pfx(true_type);
|
pfx = error_pfx(true_type);
|
||||||
|
|
||||||
*warnsuf = 0;
|
*warnsuf = 0;
|
||||||
if ((severity & (ERR_MASK|ERR_HERE|ERR_PP_LISTMACRO)) == ERR_WARNING) {
|
if (!(severity & (ERR_HERE|ERR_PP_LISTMACRO))) {
|
||||||
/*
|
const unsigned int level = WARN_IDX(severity);
|
||||||
* It's a warning without ERR_HERE defined, and we are not already
|
|
||||||
* unwinding the macros that led us here.
|
switch (severity & ERR_MASK) {
|
||||||
*/
|
case ERR_WARNING:
|
||||||
snprintf(warnsuf, sizeof warnsuf, " [-w+%s%s]",
|
snprintf(warnsuf, sizeof warnsuf, " [-w+%s%s]",
|
||||||
(true_type >= ERR_NONFATAL) ? "error=" : "",
|
(true_type >= ERR_NONFATAL) ? "error=" : "",
|
||||||
warning_name[warn_index(severity)]);
|
warning_name[level]);
|
||||||
|
break;
|
||||||
|
case ERR_DEBUG:
|
||||||
|
snprintf(warnsuf, sizeof warnsuf, " [--debug=%u]", debug_nasm);
|
||||||
|
break;
|
||||||
|
case ERR_INFO:
|
||||||
|
snprintf(warnsuf, sizeof warnsuf, " [--info=%u]", opt_verbose_info);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Not WARNING, DEBUG or INFO, not suppressible */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*linestr = 0;
|
*linestr = 0;
|
||||||
@@ -2208,8 +2205,10 @@ static void nasm_issue_error(struct nasm_errtext *et)
|
|||||||
|
|
||||||
if (true_type >= ERR_FATAL)
|
if (true_type >= ERR_FATAL)
|
||||||
die_hard(true_type, severity);
|
die_hard(true_type, severity);
|
||||||
else if (true_type >= ERR_NONFATAL)
|
else if (true_type >= ERR_NONFATAL) {
|
||||||
terminate_after_phase = true;
|
terminate_after_phase = true;
|
||||||
|
errflags_never |= ERR_UNDEAD;
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
nasm_free_error(et);
|
nasm_free_error(et);
|
||||||
@@ -2360,8 +2359,10 @@ static void help(FILE *out, const char *what)
|
|||||||
}
|
}
|
||||||
if (help_opt(with)) {
|
if (help_opt(with)) {
|
||||||
fputs(
|
fputs(
|
||||||
" -s redirect error messages to stdout\n"
|
" -s redirect messages to stdout\n"
|
||||||
" -Zfile redirect error messages to file\n"
|
" -Zfile redirect messages to file\n"
|
||||||
|
" --info[=lvl] display optional informational messages\n"
|
||||||
|
" --debug[=lvl] display NASM internal debugging messages\n"
|
||||||
, out);
|
, out);
|
||||||
}
|
}
|
||||||
if (help_optor(with, 'M')) {
|
if (help_optor(with, 'M')) {
|
||||||
|
@@ -396,7 +396,7 @@ static MMacro *pop_mmacro(MMacro **mp, MMacro *next)
|
|||||||
nasm_assert(m->refcnt > 0);
|
nasm_assert(m->refcnt > 0);
|
||||||
if (!--m->refcnt) {
|
if (!--m->refcnt) {
|
||||||
if (m->name) {
|
if (m->name) {
|
||||||
nasm_info("freeing macro `%s'", m->name);
|
nasm_debug(2, "freeing macro `%s'", m->name);
|
||||||
check_mmacro_refcounts();
|
check_mmacro_refcounts();
|
||||||
}
|
}
|
||||||
nasm_assert(!m->next);
|
nasm_assert(!m->next);
|
||||||
|
@@ -82,6 +82,8 @@ fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list val)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errflags errflags_never = 0;
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
uint8_t buffer[INSN_MAX * 2], *p;
|
uint8_t buffer[INSN_MAX * 2], *p;
|
||||||
|
144
include/error.h
144
include/error.h
@@ -40,11 +40,6 @@
|
|||||||
|
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* File pointer for error messages
|
|
||||||
*/
|
|
||||||
extern FILE *error_file; /* Error file descriptor */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Typedef for the severity field
|
* Typedef for the severity field
|
||||||
*/
|
*/
|
||||||
@@ -56,10 +51,8 @@ typedef uint32_t errflags;
|
|||||||
void printf_func(2, 3) nasm_error(errflags severity, const char *fmt, ...);
|
void printf_func(2, 3) nasm_error(errflags severity, const char *fmt, ...);
|
||||||
void printf_func(1, 2) nasm_listmsg(const char *fmt, ...);
|
void printf_func(1, 2) nasm_listmsg(const char *fmt, ...);
|
||||||
void printf_func(2, 3) nasm_listmsgf(errflags flags, const char *fmt, ...);
|
void printf_func(2, 3) nasm_listmsgf(errflags flags, const char *fmt, ...);
|
||||||
void printf_func(1, 2) nasm_debug(const char *fmt, ...);
|
void printf_func(2, 3) nasm_debug_(unsigned int level, const char *fmt, ...);
|
||||||
void printf_func(2, 3) nasm_debugf(errflags flags, const char *fmt, ...);
|
void printf_func(2, 3) nasm_info_(unsigned int level, const char *fmt, ...);
|
||||||
void printf_func(1, 2) nasm_info(const char *fmt, ...);
|
|
||||||
void printf_func(2, 3) nasm_infof(errflags flags, const char *fmt, ...);
|
|
||||||
void printf_func(1, 2) nasm_note(const char *fmt, ...);
|
void printf_func(1, 2) nasm_note(const char *fmt, ...);
|
||||||
void printf_func(2, 3) nasm_notef(errflags flags, const char *fmt, ...);
|
void printf_func(2, 3) nasm_notef(errflags flags, const char *fmt, ...);
|
||||||
void printf_func(2, 3) nasm_warn_(errflags flags, const char *fmt, ...);
|
void printf_func(2, 3) nasm_warn_(errflags flags, const char *fmt, ...);
|
||||||
@@ -77,20 +70,44 @@ fatal_func nasm_panic_from_macro(const char *func, const char *file, int line);
|
|||||||
void vprintf_func(2) nasm_verror(errflags severity, const char *fmt, va_list ap);
|
void vprintf_func(2) nasm_verror(errflags severity, const char *fmt, va_list ap);
|
||||||
fatal_func vprintf_func(2) nasm_verror_critical(errflags severity, const char *fmt, va_list ap);
|
fatal_func vprintf_func(2) nasm_verror_critical(errflags severity, const char *fmt, va_list ap);
|
||||||
|
|
||||||
|
const char *error_pfx(errflags severity);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are the error severity codes which get passed as the first
|
* These are the error severity codes which get passed as the first
|
||||||
* argument to an efunc.
|
* argument to an efunc. The order here matters!
|
||||||
*/
|
*/
|
||||||
#define ERR_LISTMSG 0x00000000 /* for the listing file only (no prefix) */
|
|
||||||
|
/* For the list file only */
|
||||||
|
#define ERR_LISTMSG 0x00000000 /* for the listing file only (comment prefix) */
|
||||||
#define ERR_NOTE 0x00000001 /* for the listing file only (with prefix) */
|
#define ERR_NOTE 0x00000001 /* for the listing file only (with prefix) */
|
||||||
#define ERR_DEBUG 0x00000002 /* debugging message */
|
|
||||||
#define ERR_INFO 0x00000003 /* information for the list file */
|
/* Non-terminating diagnostics; can be suppressed */
|
||||||
#define ERR_WARNING 0x00000004 /* warn only: no further action */
|
#define ERR_DEBUG 0x00000004 /* internal debugging message */
|
||||||
#define ERR_NONFATAL 0x00000008 /* terminate assembly after phase */
|
#define ERR_INFO 0x00000005 /* informational message */
|
||||||
#define ERR_FATAL 0x00000009 /* instantly fatal: exit with error */
|
#define ERR_WARNING 0x00000006 /* warning */
|
||||||
|
|
||||||
|
/* Errors which terminate assembly without output */
|
||||||
|
#define ERR_NONFATAL 0x00000008 /* terminate assembly after the current pass */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From this point, errors cannot be suppressed, and the C compiler is
|
||||||
|
* told that the call to nasm_verror() is terminating, to remove the
|
||||||
|
* need to generate further code.
|
||||||
|
*/
|
||||||
|
#define ERR_FATAL 0x0000000c /* terminate immediately, but perform cleanup */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Abort conditions - terminate with minimal or no cleanup.
|
||||||
|
*
|
||||||
|
* ERR_CRITICAL is used for system errors like out of memory, where the normal
|
||||||
|
* error and cleanup paths may impede informing the user of the nature of the failure.
|
||||||
|
*
|
||||||
|
* ERR_PANIC is used exclusively to trigger on bugs in the NASM code itself.
|
||||||
|
*/
|
||||||
#define ERR_CRITICAL 0x0000000e /* fatal, but minimize code before exit */
|
#define ERR_CRITICAL 0x0000000e /* fatal, but minimize code before exit */
|
||||||
#define ERR_PANIC 0x0000000f /* internal error: panic instantly
|
#define ERR_PANIC 0x0000000f /* internal error: panic instantly
|
||||||
* and dump core for reference */
|
* and call abort() to dump core for reference */
|
||||||
|
|
||||||
#define ERR_MASK 0x0000000f /* mask off the above codes */
|
#define ERR_MASK 0x0000000f /* mask off the above codes */
|
||||||
#define ERR_UNDEAD 0x00000010 /* skip if we already have errors */
|
#define ERR_UNDEAD 0x00000010 /* skip if we already have errors */
|
||||||
#define ERR_NOFILE 0x00000020 /* don't give source file name/line */
|
#define ERR_NOFILE 0x00000020 /* don't give source file name/line */
|
||||||
@@ -111,6 +128,11 @@ fatal_func vprintf_func(2) nasm_verror_critical(errflags severity, const char *f
|
|||||||
#define WARN_SHR 16 /* how far to shift right */
|
#define WARN_SHR 16 /* how far to shift right */
|
||||||
#define WARN_IDX(x) (((errflags)(x)) >> WARN_SHR)
|
#define WARN_IDX(x) (((errflags)(x)) >> WARN_SHR)
|
||||||
#define WARN_MASK ((~(errflags)0) << WARN_SHR)
|
#define WARN_MASK ((~(errflags)0) << WARN_SHR)
|
||||||
|
#define WARNING(x) ((errflags)(x) << WARN_SHR)
|
||||||
|
|
||||||
|
/* The same field is used for debug and info levels */
|
||||||
|
#define LEVEL_SHR WARN_SHR
|
||||||
|
#define LEVEL(x) WARNING(x)
|
||||||
|
|
||||||
/* This is a bitmask */
|
/* This is a bitmask */
|
||||||
#define WARN_ST_ENABLED 1 /* Warning is currently enabled */
|
#define WARN_ST_ENABLED 1 /* Warning is currently enabled */
|
||||||
@@ -154,38 +176,88 @@ errflags nasm_error_hold_pop(errhold hold, bool issue);
|
|||||||
#include "warnings.h"
|
#include "warnings.h"
|
||||||
|
|
||||||
/* True if a warning is enabled, either as a warning or an error */
|
/* True if a warning is enabled, either as a warning or an error */
|
||||||
|
extern errflags errflags_never;
|
||||||
static inline bool warn_active(errflags warn)
|
static inline bool warn_active(errflags warn)
|
||||||
{
|
{
|
||||||
enum warn_index wa = WARN_IDX(warn);
|
if (warn & errflags_never)
|
||||||
return unlikely(warning_state[wa] & WARN_ST_ENABLED);
|
return false;
|
||||||
|
|
||||||
|
return !!(warning_state[WARN_IDX(warn)] & WARN_ST_ENABLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_VARIADIC_MACROS
|
/*
|
||||||
|
* By defining MAX_DEBUG or MAX_INFO, it is possible to
|
||||||
#define nasm_warn(w, ...) \
|
* compile out messages entirely.
|
||||||
do { \
|
*/
|
||||||
if (unlikely(warn_active(w))) \
|
|
||||||
nasm_warn_(w, __VA_ARGS__); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define nasm_warn nasm_warn_
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* By defining MAX_DEBUG, we can compile out messages entirely */
|
|
||||||
#ifndef MAX_DEBUG
|
#ifndef MAX_DEBUG
|
||||||
# define MAX_DEBUG (~0U)
|
# define MAX_DEBUG UINT_MAX
|
||||||
|
#endif
|
||||||
|
#ifndef MAX_INFO
|
||||||
|
# define MAX_INFO UINT_MAX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Debug level checks */
|
/* Debug level checks */
|
||||||
|
extern unsigned int debug_nasm;
|
||||||
static inline bool debug_level(unsigned int level)
|
static inline bool debug_level(unsigned int level)
|
||||||
{
|
{
|
||||||
extern unsigned int debug_nasm;
|
|
||||||
if (is_constant(level) && level > MAX_DEBUG)
|
if (is_constant(level) && level > MAX_DEBUG)
|
||||||
return false;
|
return false;
|
||||||
return unlikely(level <= debug_nasm);
|
return unlikely(level <= debug_nasm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Info level checks */
|
||||||
|
extern unsigned int opt_verbose_info;
|
||||||
|
static inline bool info_level(unsigned int level)
|
||||||
|
{
|
||||||
|
if (is_constant(level) && level > MAX_INFO)
|
||||||
|
return false;
|
||||||
|
return unlikely(level <= opt_verbose_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_VARIADIC_MACROS
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Marked unlikely() to avoid excessive speed penalties on disabled warnings;
|
||||||
|
* if the warning is issued then the performance penalty is substantial
|
||||||
|
* anyway.
|
||||||
|
*/
|
||||||
|
#define nasm_warn(w, ...) \
|
||||||
|
do { \
|
||||||
|
const errflags _w = (w); \
|
||||||
|
if (unlikely(warn_active(_w))) { \
|
||||||
|
nasm_warn_(_w, __VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define nasm_info(l, ...) \
|
||||||
|
do { \
|
||||||
|
const unsigned int _l = (l); \
|
||||||
|
if (unlikely(info_level(_l))) \
|
||||||
|
nasm_info_(_l, __VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define nasm_debug(l, ...) \
|
||||||
|
do { \
|
||||||
|
const unsigned int _l = (l); \
|
||||||
|
if (unlikely(debug_level(_l))) \
|
||||||
|
nasm_debug_(_l, __VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define nasm_warn nasm_warn_
|
||||||
|
#if MAX_DEBUG
|
||||||
|
# define nasm_debug nasm_debug_
|
||||||
|
#else
|
||||||
|
# define nasm_debug (void)
|
||||||
|
#endif
|
||||||
|
#if MAX_INFO
|
||||||
|
# define nasm_info nasm_info_
|
||||||
|
#else
|
||||||
|
# define nasm_info (void)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif /* NASM_ERROR_H */
|
#endif /* NASM_ERROR_H */
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
#include "compiler.h"
|
|
||||||
|
|
||||||
FILE *error_file;
|
|
@@ -228,10 +228,10 @@ static void bin_cleanup(void)
|
|||||||
uint64_t pend;
|
uint64_t pend;
|
||||||
int h;
|
int h;
|
||||||
|
|
||||||
if (debug_level(1)) {
|
if (debug_level(2)) {
|
||||||
nasm_debug("bin_cleanup: Sections were initially referenced in this order:\n");
|
nasm_debug(2, "bin_cleanup: Sections were initially referenced in this order:\n");
|
||||||
for (h = 0, s = sections; s; h++, s = s->next)
|
for (h = 0, s = sections; s; h++, s = s->next)
|
||||||
nasm_debug("%i. %s\n", h, s->name);
|
nasm_debug(2, "%i. %s\n", h, s->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assembly has completed, so now we need to generate the output file.
|
/* Assembly has completed, so now we need to generate the output file.
|
||||||
@@ -513,11 +513,11 @@ static void bin_cleanup(void)
|
|||||||
if (h)
|
if (h)
|
||||||
nasm_fatal("circular vfollows path detected");
|
nasm_fatal("circular vfollows path detected");
|
||||||
|
|
||||||
if (debug_level(1)) {
|
if (debug_level(2)) {
|
||||||
nasm_debug("bin_cleanup: Confirm final section order for output file:\n");
|
nasm_debug(2, "bin_cleanup: Confirm final section order for output file:\n");
|
||||||
for (h = 0, s = sections; s && (s->flags & TYPE_PROGBITS);
|
for (h = 0, s = sections; s && (s->flags & TYPE_PROGBITS);
|
||||||
h++, s = s->next)
|
h++, s = s->next)
|
||||||
nasm_debug("%i. %s\n", h, s->name);
|
nasm_debug(2, "%i. %s\n", h, s->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Step 5: Apply relocations. */
|
/* Step 5: Apply relocations. */
|
||||||
|
@@ -760,10 +760,8 @@ static void elf_deflabel(char *name, int32_t segment, int64_t offset,
|
|||||||
int bind, type; /* st_info components */
|
int bind, type; /* st_info components */
|
||||||
const struct elf_section *sec = NULL;
|
const struct elf_section *sec = NULL;
|
||||||
|
|
||||||
if (debug_level(2)) {
|
nasm_debug(2, " elf_deflabel: %s, seg=%"PRIx32", off=%"PRIx64", is_global=%d, %s\n",
|
||||||
nasm_debug(" elf_deflabel: %s, seg=%"PRIx32", off=%"PRIx64", is_global=%d, %s\n",
|
name, segment, offset, is_global, special);
|
||||||
name, segment, offset, is_global, special);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
|
if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
|
||||||
/*
|
/*
|
||||||
|
@@ -781,9 +781,8 @@ static void obj_deflabel(char *name, int32_t segment,
|
|||||||
int i;
|
int i;
|
||||||
bool used_special = false; /* have we used the special text? */
|
bool used_special = false; /* have we used the special text? */
|
||||||
|
|
||||||
if (debug_level(2))
|
nasm_debug(2, " obj_deflabel: %s, seg=%"PRIx32", off=%"PRIx64", is_global=%d, %s\n",
|
||||||
nasm_debug(" obj_deflabel: %s, seg=%"PRIx32", off=%"PRIx64", is_global=%d, %s\n",
|
name, segment, offset, is_global, special);
|
||||||
name, segment, offset, is_global, special);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If it's a special-retry from pass two, discard it.
|
* If it's a special-retry from pass two, discard it.
|
||||||
@@ -1337,8 +1336,7 @@ static int32_t obj_segment(char *name, int *bits)
|
|||||||
* using the pointer it gets passed. That way we save memory,
|
* using the pointer it gets passed. That way we save memory,
|
||||||
* by sponging off the label manager.
|
* by sponging off the label manager.
|
||||||
*/
|
*/
|
||||||
if (debug_level(3))
|
nasm_debug(3, " obj_segment: < %s >, *bits=%d\n", name, *bits);
|
||||||
nasm_debug(" obj_segment: < %s >, *bits=%d\n", name, *bits);
|
|
||||||
|
|
||||||
if (!name) {
|
if (!name) {
|
||||||
*bits = 16;
|
*bits = 16;
|
||||||
|
Reference in New Issue
Block a user