aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/mac/handler/dynamic_images.cc73
1 files changed, 63 insertions, 10 deletions
diff --git a/src/client/mac/handler/dynamic_images.cc b/src/client/mac/handler/dynamic_images.cc
index 32a57e82..87d06706 100644
--- a/src/client/mac/handler/dynamic_images.cc
+++ b/src/client/mac/handler/dynamic_images.cc
@@ -27,14 +27,69 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include <mach-o/nlist.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <algorithm>
+extern "C" { // needed to compile on Leopard
+ #include <mach-o/nlist.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+}
+#include <algorithm>
#include "client/mac/handler/dynamic_images.h"
namespace google_breakpad {
+
+//==============================================================================
+// Returns the size of the memory region containing |address| and the
+// number of bytes from |address| to the end of the region.
+static vm_size_t GetMemoryRegionSize(task_port_t target_task,
+ const void* address,
+ vm_size_t *size_to_end) {
+ vm_address_t stack_region_base = (vm_address_t)address;
+ vm_size_t stack_region_size;
+ natural_t nesting_level = 0;
+ vm_region_submap_info submap_info;
+ mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT;
+
+ kern_return_t result =
+ vm_region_recurse(target_task, &stack_region_base, &stack_region_size,
+ &nesting_level,
+ reinterpret_cast<vm_region_recurse_info_t>(&submap_info),
+ &info_count);
+
+ if (result == KERN_SUCCESS) {
+ *size_to_end = stack_region_base + stack_region_size - (vm_address_t)address;
+ } else {
+ stack_region_size = 0;
+ *size_to_end = 0;
+ }
+
+ return stack_region_size;
+}
+
+#define kMaxStringLength 8192
+//==============================================================================
+// Reads a NULL-terminated string from another task.
+//
+// Warning! This will not read any strings longer than kMaxStringLength-1
+//
+static void* ReadTaskString(task_port_t target_task,
+ const void* address) {
+ // The problem is we don't know how much to read until we know how long
+ // the string is. And we don't know how long the string is, until we've read
+ // the memory! So, we'll try to read kMaxStringLength bytes
+ // (or as many bytes as we can until we reach the end of the vm region).
+ vm_size_t size_to_end;
+ GetMemoryRegionSize(target_task, address, &size_to_end);
+
+ if (size_to_end > 0) {
+ vm_size_t size_to_read =
+ size_to_end > kMaxStringLength ? kMaxStringLength : size_to_end;
+
+ return ReadTaskMemory(target_task, address, size_to_read);
+ }
+
+ return NULL;
+}
//==============================================================================
// Reads an address range from another task. A block of memory is malloced
@@ -173,7 +228,7 @@ void DynamicImages::ReadImageInfoForTask() {
if (!header)
break; // bail on this dynamic image
-
+
// Now determine the total amount we really want to read based on the
// size of the load commands. We need the header plus all of the
// load commands.
@@ -186,15 +241,13 @@ void DynamicImages::ReadImageInfoForTask() {
// Read the file name from the task's memory space.
char *file_path = NULL;
if (info.file_path_) {
- // Although we're reading 0x2000 bytes, this is copied in the
+ // Although we're reading kMaxStringLength bytes, it's copied in the
// the DynamicImage constructor below with the correct string length,
// so it's not really wasting memory.
file_path = reinterpret_cast<char*>
- (ReadTaskMemory(task_,
- info.file_path_,
- 0x2000));
+ (ReadTaskString(task_, info.file_path_));
}
-
+
// Create an object representing this image and add it to our list.
DynamicImage *new_image = new DynamicImage(header,
header_size,