diff options
Diffstat (limited to 'src/usr/trace/runtime/rt_service.C')
-rw-r--r-- | src/usr/trace/runtime/rt_service.C | 119 |
1 files changed, 114 insertions, 5 deletions
diff --git a/src/usr/trace/runtime/rt_service.C b/src/usr/trace/runtime/rt_service.C index 2bb697d3e..e7eda7280 100644 --- a/src/usr/trace/runtime/rt_service.C +++ b/src/usr/trace/runtime/rt_service.C @@ -25,10 +25,15 @@ #include <limits.h> #include <assert.h> #include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> #include <runtime/interface.h> namespace TRACE { + // Value was chosen empirically from trace lengths during the IPL. + static const size_t DEFAULT_TRACE_LENGTH = 128; Service::Service() { @@ -55,14 +60,34 @@ namespace TRACE } } - char output[KILOBYTE]; - vsprintf(output, i_fmt, i_args); // TODO: RTC 79420 : - // Potential buffer overrun. - g_hostInterfaces->puts(output); + size_t compName_len = strnlen(i_td->iv_compName, + sizeof(i_td->iv_compName)); + + char output[DEFAULT_TRACE_LENGTH]; + memcpy(output, i_td->iv_compName, compName_len); + output[compName_len] = ':'; + size_t length = vsnprintf(&output[compName_len+1], + DEFAULT_TRACE_LENGTH-(compName_len+1), + i_fmt, i_args); + + if (unlikely((compName_len + 1 + length + 1) > DEFAULT_TRACE_LENGTH)) + { + char* long_output = new char[compName_len + 1 + length + 1]; + memcpy(long_output, i_td->iv_compName, compName_len); + long_output[compName_len] = ':'; + vsprintf(&long_output[compName_len+1], i_fmt, i_args); + g_hostInterfaces->puts(long_output); + delete[] long_output; + } + else + { + g_hostInterfaces->puts(output); + } } void Service::writeBinEntry(ComponentDesc* i_td, trace_hash_val i_hash, + const char * i_fmt, uint32_t i_ine, const void* i_ptr, uint32_t i_size, @@ -76,7 +101,91 @@ namespace TRACE } } - // TODO: RTC 79420 + size_t compName_len = strnlen(i_td->iv_compName, + sizeof(i_td->iv_compName)); + + // Output header. + char output[DEFAULT_TRACE_LENGTH]; + memcpy(output, i_td->iv_compName, compName_len); + output[compName_len] = ':'; + size_t length = vsnprintf(&output[compName_len+1], + DEFAULT_TRACE_LENGTH-(compName_len+1), + i_fmt, NULL); + + if(unlikely((compName_len + 1 + length + 1) > DEFAULT_TRACE_LENGTH)) + { + char* long_output = new char[compName_len + length + 1]; + memcpy(long_output, i_td->iv_compName, compName_len); + long_output[compName_len] = ':'; + vsprintf(&long_output[compName_len+1], i_fmt, NULL); + g_hostInterfaces->puts(long_output); + delete[] long_output; + } + else + { + g_hostInterfaces->puts(output); + } + + // Output binary data. + // Format is: + // ~[0x0000] 01234567 01234567 01234567 01234567 *012345689abcdef* + static size_t BINARY_FORMAT_LENGTH = + 68 + sizeof(ComponentDesc::iv_compName) + 1; + + size_t pos = 0; + while (pos < i_size) + { + char bin_output[BINARY_FORMAT_LENGTH]; + memcpy(bin_output, i_td->iv_compName, compName_len); + size_t output_pos = compName_len + + sprintf(&bin_output[compName_len], + ":~[0x%04hx]", (int) pos); + + for (int i = 0; i < 16; ++i) + { + if ((i % 4) == 0) + { + bin_output[output_pos++] = ' '; + } + if ((pos + i) < i_size) + { + output_pos += + sprintf(&bin_output[output_pos], "%02x", + ((const char*)i_ptr)[pos+i]); + } + else + { + bin_output[output_pos++] = ' '; + bin_output[output_pos++] = ' '; + } + } + + for (int i = 0; i < 4; i++) + { + bin_output[output_pos++] = ' '; + } + bin_output[output_pos++] = '*'; + + for (int i = 0; i < 16; ++i) + { + char ch = ' '; + if ((pos + i) < i_size) + { + ch = ((const char*) i_ptr)[pos+i]; + if (!isprint(ch)) + { + ch = '.'; + } + } + bin_output[output_pos++] = ch; + } + bin_output[output_pos++] = '*'; + bin_output[output_pos++] = '\0'; + + g_hostInterfaces->puts(bin_output); + + pos += 16; + } } |