aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/gallium/auxiliary/util
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/gallium/auxiliary/util')
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_debug_memory.c82
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format.c14
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format.h5
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format_pack.py2
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_rect.c9
5 files changed, 99 insertions, 13 deletions
diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_memory.c b/mesalib/src/gallium/auxiliary/util/u_debug_memory.c
index e24a8bc0b..4bf26a524 100644
--- a/mesalib/src/gallium/auxiliary/util/u_debug_memory.c
+++ b/mesalib/src/gallium/auxiliary/util/u_debug_memory.c
@@ -48,6 +48,16 @@
#define DEBUG_MEMORY_MAGIC 0x6e34090aU
#define DEBUG_MEMORY_STACK 0 /* XXX: disabled until we have symbol lookup */
+/**
+ * Set to 1 to enable checking of freed blocks of memory.
+ * Basically, don't really deallocate freed memory; keep it in the list
+ * but mark it as freed and do extra checking in debug_memory_check().
+ * This can detect some cases of use-after-free. But note that since we
+ * never really free anything this will use a lot of memory.
+ */
+#define DEBUG_FREED_MEMORY 0
+#define DEBUG_FREED_BYTE 0x33
+
struct debug_memory_header
{
@@ -61,7 +71,10 @@ struct debug_memory_header
struct debug_stack_frame backtrace[DEBUG_MEMORY_STACK];
#endif
size_t size;
-
+#if DEBUG_FREED_MEMORY
+ boolean freed; /**< Is this a freed block? */
+#endif
+
unsigned magic;
};
@@ -127,6 +140,9 @@ debug_malloc(const char *file, unsigned line, const char *function,
hdr->function = function;
hdr->size = size;
hdr->magic = DEBUG_MEMORY_MAGIC;
+#if DEBUG_FREED_MEMORY
+ hdr->freed = FALSE;
+#endif
#if DEBUG_MEMORY_STACK
debug_backtrace_capture(hdr->backtrace, 0, DEBUG_MEMORY_STACK);
@@ -169,6 +185,17 @@ debug_free(const char *file, unsigned line, const char *function,
debug_assert(0);
}
+#if DEBUG_FREED_MEMORY
+ /* Check for double-free */
+ assert(!hdr->freed);
+ /* Mark the block as freed but don't really free it */
+ hdr->freed = TRUE;
+ /* Save file/line where freed */
+ hdr->file = file;
+ hdr->line = line;
+ /* set freed memory to special value */
+ memset(ptr, DEBUG_FREED_BYTE, hdr->size);
+#else
pipe_mutex_lock(list_mutex);
LIST_DEL(&hdr->head);
pipe_mutex_unlock(list_mutex);
@@ -176,6 +203,7 @@ debug_free(const char *file, unsigned line, const char *function,
ftr->magic = 0;
os_free(hdr);
+#endif
}
void *
@@ -235,6 +263,9 @@ debug_realloc(const char *file, unsigned line, const char *function,
new_hdr->function = old_hdr->function;
new_hdr->size = new_size;
new_hdr->magic = DEBUG_MEMORY_MAGIC;
+#if DEBUG_FREED_MEMORY
+ new_hdr->freed = FALSE;
+#endif
new_ftr = footer_from_header(new_hdr);
new_ftr->magic = DEBUG_MEMORY_MAGIC;
@@ -314,3 +345,52 @@ debug_memory_end(unsigned long start_no)
debug_printf("No memory leaks detected.\n");
}
}
+
+
+/**
+ * We can periodically call this from elsewhere to do a basic sanity
+ * check of the heap memory we've allocated.
+ */
+void
+debug_memory_check(void)
+{
+ struct list_head *entry;
+
+ entry = list.prev;
+ for (; entry != &list; entry = entry->prev) {
+ struct debug_memory_header *hdr;
+ struct debug_memory_footer *ftr;
+ const char *ptr;
+
+ hdr = LIST_ENTRY(struct debug_memory_header, entry, head);
+ ftr = footer_from_header(hdr);
+ ptr = (const char *) data_from_header(hdr);
+
+ if (hdr->magic != DEBUG_MEMORY_MAGIC) {
+ debug_printf("%s:%u:%s: bad or corrupted memory %p\n",
+ hdr->file, hdr->line, hdr->function, ptr);
+ debug_assert(0);
+ }
+
+ if (ftr->magic != DEBUG_MEMORY_MAGIC) {
+ debug_printf("%s:%u:%s: buffer overflow %p\n",
+ hdr->file, hdr->line, hdr->function, ptr);
+ debug_assert(0);
+ }
+
+#if DEBUG_FREED_MEMORY
+ /* If this block is marked as freed, check that it hasn't been touched */
+ if (hdr->freed) {
+ int i;
+ for (i = 0; i < hdr->size; i++) {
+ if (ptr[i] != DEBUG_FREED_BYTE) {
+ debug_printf("Memory error: byte %d of block at %p of size %d is 0x%x\n",
+ i, ptr, hdr->size, ptr[i]);
+ debug_printf("Block was freed at %s:%d\n", hdr->file, hdr->line);
+ }
+ assert(ptr[i] == DEBUG_FREED_BYTE);
+ }
+ }
+#endif
+ }
+}
diff --git a/mesalib/src/gallium/auxiliary/util/u_format.c b/mesalib/src/gallium/auxiliary/util/u_format.c
index f572a612e..ddce95601 100644
--- a/mesalib/src/gallium/auxiliary/util/u_format.c
+++ b/mesalib/src/gallium/auxiliary/util/u_format.c
@@ -147,9 +147,12 @@ util_format_is_array(const struct util_format_description *desc)
}
for (chan = 0; chan < desc->nr_channels; ++chan) {
- if (desc->swizzle[chan] != chan)
+ if (desc->channel[chan].size != desc->channel[0].size)
return FALSE;
+ if (desc->channel[chan].type == UTIL_FORMAT_TYPE_VOID && (chan + 1) == desc->nr_channels)
+ continue;
+
if (desc->channel[chan].type != desc->channel[0].type)
return FALSE;
@@ -158,9 +161,16 @@ util_format_is_array(const struct util_format_description *desc)
if (desc->channel[chan].pure_integer != desc->channel[0].pure_integer)
return FALSE;
+ }
- if (desc->channel[chan].size != desc->channel[0].size)
+ if (desc->nr_channels == 4) {
+ if (desc->swizzle[3] < 3)
return FALSE;
+ } else {
+ for (chan = 0; chan < desc->nr_channels; ++chan) {
+ if (desc->swizzle[chan] != chan)
+ return FALSE;
+ }
}
return TRUE;
diff --git a/mesalib/src/gallium/auxiliary/util/u_format.h b/mesalib/src/gallium/auxiliary/util/u_format.h
index a718389dd..25bfd234b 100644
--- a/mesalib/src/gallium/auxiliary/util/u_format.h
+++ b/mesalib/src/gallium/auxiliary/util/u_format.h
@@ -592,7 +592,10 @@ util_format_is_pure_uint(enum pipe_format format);
/**
* Whether the format is a simple array format where all channels
- * are of the same type and can be loaded from memory as a vector
+ * are of the same type and can be loaded from memory as a vector.
+ *
+ * If format is 4 channel it can be swizzled (eg BGRA) as long
+ * as the alpha is the 3rd channel.
*/
boolean
util_format_is_array(const struct util_format_description *desc);
diff --git a/mesalib/src/gallium/auxiliary/util/u_format_pack.py b/mesalib/src/gallium/auxiliary/util/u_format_pack.py
index 0b3a890d5..565d059c3 100644
--- a/mesalib/src/gallium/auxiliary/util/u_format_pack.py
+++ b/mesalib/src/gallium/auxiliary/util/u_format_pack.py
@@ -383,7 +383,7 @@ def conversion_expr(src_channel,
if dst_channel.norm or dst_channel.type == FIXED:
dst_one = get_one(dst_channel)
if dst_channel.size <= 23:
- value = '(%s * 0x%x)' % (value, dst_one)
+ value = 'util_iround(%s * 0x%x)' % (value, dst_one)
else:
# bigger than single precision mantissa, use double
value = '(%s * (double)0x%x)' % (value, dst_one)
diff --git a/mesalib/src/gallium/auxiliary/util/u_rect.c b/mesalib/src/gallium/auxiliary/util/u_rect.c
index 59bebbcb7..d00568f1f 100644
--- a/mesalib/src/gallium/auxiliary/util/u_rect.c
+++ b/mesalib/src/gallium/auxiliary/util/u_rect.c
@@ -144,11 +144,7 @@ util_fill_rect(ubyte * dst,
dst += dst_stride;
}
break;
- case 8:
- case 12:
- case 16:
- case 24:
- case 32:
+ default:
for (i = 0; i < height; i++) {
ubyte *row = dst;
for (j = 0; j < width; j++) {
@@ -158,8 +154,5 @@ util_fill_rect(ubyte * dst,
dst += dst_stride;
}
break;
- default:
- assert(0);
- break;
}
}