|
@@ -33,20 +33,20 @@ static unsigned int hex(char c)
|
|
|
return c - 'A' + 10;
|
|
|
}
|
|
|
|
|
|
-static void read_objdump_line(const char *line, size_t line_len, void **buf,
|
|
|
- size_t *len)
|
|
|
+static size_t read_objdump_line(const char *line, size_t line_len, void *buf,
|
|
|
+ size_t len)
|
|
|
{
|
|
|
const char *p;
|
|
|
- size_t i;
|
|
|
+ size_t i, j = 0;
|
|
|
|
|
|
/* Skip to a colon */
|
|
|
p = strchr(line, ':');
|
|
|
if (!p)
|
|
|
- return;
|
|
|
+ return 0;
|
|
|
i = p + 1 - line;
|
|
|
|
|
|
/* Read bytes */
|
|
|
- while (*len) {
|
|
|
+ while (j < len) {
|
|
|
char c1, c2;
|
|
|
|
|
|
/* Skip spaces */
|
|
@@ -65,20 +65,26 @@ static void read_objdump_line(const char *line, size_t line_len, void **buf,
|
|
|
if (i < line_len && line[i] && !isspace(line[i]))
|
|
|
break;
|
|
|
/* Store byte */
|
|
|
- *(unsigned char *)*buf = (hex(c1) << 4) | hex(c2);
|
|
|
- *buf += 1;
|
|
|
- *len -= 1;
|
|
|
+ *(unsigned char *)buf = (hex(c1) << 4) | hex(c2);
|
|
|
+ buf += 1;
|
|
|
+ j++;
|
|
|
}
|
|
|
+ /* return number of successfully read bytes */
|
|
|
+ return j;
|
|
|
}
|
|
|
|
|
|
-static int read_objdump_output(FILE *f, void **buf, size_t *len)
|
|
|
+static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr)
|
|
|
{
|
|
|
char *line = NULL;
|
|
|
- size_t line_len;
|
|
|
+ size_t line_len, off_last = 0;
|
|
|
ssize_t ret;
|
|
|
int err = 0;
|
|
|
+ u64 addr;
|
|
|
+
|
|
|
+ while (off_last < *len) {
|
|
|
+ size_t off, read_bytes, written_bytes;
|
|
|
+ unsigned char tmp[BUFSZ];
|
|
|
|
|
|
- while (1) {
|
|
|
ret = getline(&line, &line_len, f);
|
|
|
if (feof(f))
|
|
|
break;
|
|
@@ -87,9 +93,28 @@ static int read_objdump_output(FILE *f, void **buf, size_t *len)
|
|
|
err = -1;
|
|
|
break;
|
|
|
}
|
|
|
- read_objdump_line(line, ret, buf, len);
|
|
|
+
|
|
|
+ /* read objdump data into temporary buffer */
|
|
|
+ read_bytes = read_objdump_line(line, ret, tmp, sizeof(tmp));
|
|
|
+ if (!read_bytes)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (sscanf(line, "%"PRIx64, &addr) != 1)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ /* copy it from temporary buffer to 'buf' according
|
|
|
+ * to address on current objdump line */
|
|
|
+ off = addr - start_addr;
|
|
|
+ if (off >= *len)
|
|
|
+ break;
|
|
|
+ written_bytes = MIN(read_bytes, *len - off);
|
|
|
+ memcpy(buf + off, tmp, written_bytes);
|
|
|
+ off_last = off + written_bytes;
|
|
|
}
|
|
|
|
|
|
+ /* len returns number of bytes that could not be read */
|
|
|
+ *len -= off_last;
|
|
|
+
|
|
|
free(line);
|
|
|
|
|
|
return err;
|
|
@@ -120,7 +145,7 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf,
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- ret = read_objdump_output(f, &buf, &len);
|
|
|
+ ret = read_objdump_output(f, buf, &len, addr);
|
|
|
if (len) {
|
|
|
pr_debug("objdump read too few bytes\n");
|
|
|
if (!ret)
|