summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Krause <minipli@googlemail.com>2015-06-17 15:39:38 +0200
committerPaul Moore <pmoore@redhat.com>2015-07-06 11:29:58 -0400
commit1ff6f3e6521d787e52fe328b862094898fc0b77e (patch)
tree0f04a43fc20ccc3583542233b7dff47ee9a65b0b
parentccaf7d240c2fe034a323af2783ddec6297ae37e6 (diff)
downloadlibseccomp-1ff6f3e6521d787e52fe328b862094898fc0b77e.tar.gz
db: optimize masked compares
If the masked compare is a tautology we don't need to generate instructions for the runtime test. It'll always be true. This patch handles the case for 32 bit arches and partially for 64 bit arches. The cases where either the upper half or the lower half is a tautology is still TODO. Signed-off-by: Mathias Krause <minipli@googlemail.com> [PM: minor function name changes to better match existing style] Signed-off-by: Paul Moore <pmoore@redhat.com>
-rw-r--r--src/db.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/db.c b/src/db.c
index d6580ee..604d058 100644
--- a/src/db.c
+++ b/src/db.c
@@ -825,6 +825,38 @@ int db_syscall_priority(struct db_filter *db,
}
/**
+ * Test if the argument filter can be skipped because it's a tautology
+ * @param arg argument filter
+ *
+ * If this argument filter applied to the lower 32 bit can be skipped this
+ * function returns false.
+ *
+ */
+static bool _db_arg_cmp_need_lo(const struct db_api_arg *arg)
+{
+ if (arg->op == SCMP_CMP_MASKED_EQ && D64_LO(arg->mask) == 0)
+ return false;
+
+ return true;
+}
+
+/**
+ * Test if the argument filter can be skipped because it's a tautology
+ * @param arg argument filter
+ *
+ * If this argument filter applied to the upper 32 bit can be skipped this
+ * function returns false.
+ *
+ */
+static bool _db_arg_cmp_need_hi(const struct db_api_arg *arg)
+{
+ if (arg->op == SCMP_CMP_MASKED_EQ && D64_HI(arg->mask) == 0)
+ return false;
+
+ return true;
+}
+
+/**
* Fixup the node based on the op/mask
* @param node the chain node
*
@@ -873,6 +905,13 @@ static struct db_sys_list *_db_rule_gen_64(const struct arch_def *arch,
if (chain[iter].valid == 0)
continue;
+ /* TODO: handle the case were either hi or lo isn't needed */
+
+ /* skip generating instruction which are no-ops */
+ if (!_db_arg_cmp_need_hi(&chain[iter]) &&
+ !_db_arg_cmp_need_lo(&chain[iter]))
+ continue;
+
c_iter_hi = malloc(sizeof(*c_iter_hi));
if (c_iter_hi == NULL)
goto gen_64_failure;
@@ -1005,6 +1044,10 @@ static struct db_sys_list *_db_rule_gen_32(const struct arch_def *arch,
if (chain[iter].valid == 0)
continue;
+ /* skip generating instructions which are no-ops */
+ if (!_db_arg_cmp_need_lo(&chain[iter]))
+ continue;
+
c_iter = malloc(sizeof(*c_iter));
if (c_iter == NULL)
goto gen_32_failure;
@@ -1013,6 +1056,7 @@ static struct db_sys_list *_db_rule_gen_32(const struct arch_def *arch,
c_iter->arg = chain[iter].arg;
c_iter->arg_offset = arch_arg_offset(arch, c_iter->arg);
c_iter->op = chain[iter].op;
+ /* implicitly strips off the upper 32 bit */
c_iter->mask = chain[iter].mask;
c_iter->datum = chain[iter].datum;