@@ -59,6 +59,92 @@ __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) void cil_tree_e
exit(1);
}
+struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **path, int* is_cil)
+{
+ if (!node) {
+ return NULL;
+ }
+
+ node = node->parent;
+
+ while (node) {
+ if (node->flavor == CIL_NODE && node->data == NULL) {
+ if (node->cl_head->data == CIL_KEY_SRC_INFO) {
+ /* Parse Tree */
+ *path = node->cl_head->next->next->data;
+ *is_cil = (node->cl_head->next->data == CIL_KEY_SRC_CIL);
+ return node;
+ }
+ node = node->parent;
+ } else if (node->flavor == CIL_SRC_INFO) {
+ /* AST */
+ struct cil_src_info *info = node->data;
+ *path = info->path;
+ *is_cil = info->is_cil;
+ return node;
+ } else {
+ if (node->flavor == CIL_CALL) {
+ struct cil_call *call = node->data;
+ node = NODE(call->macro);
+ } else if (node->flavor == CIL_BLOCKINHERIT) {
+ struct cil_blockinherit *inherit = node->data;
+ node = NODE(inherit->block);
+ } else {
+ node = node->parent;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+char *cil_tree_get_cil_path(struct cil_tree_node *node)
+{
+ char *path = NULL;
+ int is_cil;
+
+ while (node) {
+ node = cil_tree_get_next_path(node, &path, &is_cil);
+ if (node && is_cil) {
+ return path;
+ }
+ }
+
+ return NULL;
+}
+
+__attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *node, enum cil_log_level lvl, const char* msg, ...)
+{
+ va_list ap;
+
+ va_start(ap, msg);
+ cil_vlog(lvl, msg, ap);
+ va_end(ap);
+
+ if (node) {
+ char *path = NULL;
+ int is_cil;
+ unsigned hll_line = node->hll_line;
+
+ path = cil_tree_get_cil_path(node);
+
+ if (path != NULL) {
+ cil_log(lvl, " at line %d of %s", node->line, path);
+ }
+
+ while (node) {
+ node = cil_tree_get_next_path(node, &path, &is_cil);
+ if (node && !is_cil) {
+ cil_log(lvl," (from line %d of %s)", hll_line, path);
+ path = NULL;
+ hll_line = node->hll_line;
+ }
+ }
+ }
+
+ cil_log(lvl,"\n");
+}
+
int cil_tree_init(struct cil_tree **tree)
{
struct cil_tree *new_tree = cil_malloc(sizeof(*new_tree));
@@ -51,6 +51,10 @@ struct cil_tree_node {
void *data;
};
+struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **path, int* is_cil);
+char *cil_tree_get_cil_path(struct cil_tree_node *node);
+__attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *node, enum cil_log_level lvl, const char* msg, ...);
+
int cil_tree_init(struct cil_tree **tree);
void cil_tree_destroy(struct cil_tree **tree);
void cil_tree_subtree_destroy(struct cil_tree_node *node);
Provide more detailed log messages containing all relevant CIL and high-level language source file information through cil_tree_log(). cil_tree_log() uses two new functions: cil_tree_get_next_path() and cil_tree_get_cil_path(). cil_tree_get_next_path() traverses up the parse tree or AST until it finds the next CIL or high-level language source information nodes. It will return the path and whether or not the path is for a CIL file. cil_tree_get_cil_path() uses cil_tree_get_next_path() to return the CIL path. Example cil_tree_log() message: Problem at line 21 of policy.cil (from line 11 of foo.hll) (from line 2 of bar.hll) Signed-off-by: James Carter <jwcart2@tycho.nsa.gov> --- libsepol/cil/src/cil_tree.c | 86 +++++++++++++++++++++++++++++++++++++++++++++ libsepol/cil/src/cil_tree.h | 4 +++ 2 files changed, 90 insertions(+)