summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHyeongsik Min <hyeongsik.min@samsung.com>2017-02-28 15:27:35 +0900
committerHyeongsik Min <hyeongsik.min@samsung.com>2017-02-28 17:45:37 +0900
commit00f00ad5c8d683c0ec7cba40bb06327424031a7e (patch)
treeafc9fe08c16be435bcfcc0cb6aed2b66ef419b35
parent59c99b613242d861f212b8bf00d17b20fa4131c0 (diff)
downloadmemps-00f00ad5c8d683c0ec7cba40bb06327424031a7e.tar.gz
memps-00f00ad5c8d683c0ec7cba40bb06327424031a7e.tar.bz2
memps-00f00ad5c8d683c0ec7cba40bb06327424031a7e.zip
Memps fails to parse smaps and gets crash when kernel shows anon name information in /proc/smaps, because kernel adds additional line to print the information. Instead of using fixed smaps line count, this patch checks every line to find VMA address line. Change-Id: I5eaad65804f9cae67bfc62b6625b4b7da0eb27aa Signed-off-by: Hyeongsik Min <hyeongsik.min@samsung.com>
-rw-r--r--memps.c119
1 files changed, 16 insertions, 103 deletions
diff --git a/memps.c b/memps.c
index fd821b0..d944aa5 100644
--- a/memps.c
+++ b/memps.c
@@ -110,7 +110,6 @@ struct geminfo {
unsigned hcount;
};
-static int smaps_lcnt;
static int sum;
static int verbos;
@@ -319,17 +318,17 @@ static geminfo *load_geminfo(void)
* 01234567890123456789012345678901234567890123456789012345678901234567890123456789
* 0 1 2 3 4 5 6 7
*/
-mapinfo *read_mapinfo(char** smaps, int line_cnt)
+mapinfo *read_mapinfo(char** smaps)
{
char* line;
mapinfo *mi;
int len;
int n;
- if ((--line_cnt <= 0) || (line = cgets(smaps)) == 0)
+ if ((line = cgets(smaps)) == 0)
return 0;
- len = strlen(line);
+ len = strlen(line);
if (len < 1)
return 0;
@@ -342,8 +341,13 @@ mapinfo *read_mapinfo(char** smaps, int line_cnt)
if (n == 3 && !mi->name)
mi->name = strndup("[anon]", strlen("[anon]"));
+ else if (n <= 3) {
+ fprintf(stderr,"Fail to parse smaps\n");
+ free(mi);
+ return 0;
+ }
- while (line_cnt-- && (line = cgets(smaps))) {
+ while ((line = cgets(smaps))) {
if (sscanf(line, "Size: %d kB", &mi->size) == 1) {}
else if (sscanf(line, "Rss: %d kB", &mi->rss) == 1) {}
else if (sscanf(line, "Pss: %d kB", &mi->pss) == 1) {}
@@ -352,6 +356,12 @@ mapinfo *read_mapinfo(char** smaps, int line_cnt)
else if (sscanf(line, "Private_Clean: %d kB", &mi->private_clean) == 1) {}
else if (sscanf(line, "Private_Dirty: %d kB", &mi->private_dirty) == 1) {}
else if (sscanf(line, "Swap: %d kB", &mi->swap) == 1) {}
+ if (*smaps) {
+ /* Drain lines until it meets next VMA address */
+ char next = **smaps;
+ if ((next >= '0' && next <= '9') || (next >= 'a' && next <= 'f'))
+ break;
+ }
}
return mi;
@@ -657,7 +667,7 @@ mapinfo *load_maps(int pid)
if (smaps == NULL)
return 0;
- while ((mi = read_mapinfo(&smaps, smaps_lcnt)) != 0) {
+ while ((mi = read_mapinfo(&smaps)) != 0) {
if (milist) {
if ((!strcmp(mi->name, milist->name)
&& (mi->name[0] != '['))) {
@@ -1186,109 +1196,12 @@ static int show_map_new(int pid)
return 1;
}
-int get_fixed_smaps_lcnt(void)
-{
- struct utsname buf;
- int ret;
-
- ret = uname(&buf);
-
- if (!ret) {
- char *pch;
- char str[3];
- int sub_version;
- pch = strstr(buf.release, ".");
- strncpy(str, pch+1, 2);
- sub_version = atoi(str);
-
- if (buf.release[0] >= '4') {
- if (sub_version >= 4)
- ret = 19;
- /* Vma, Size, Rss, Pss, Shared_Clean, Shard_Dirty,
- * Private_Clean, Private_Drity,
- * Referenced, Anonymous, AnonHugePages, Shared_Hugetlb,
- * Private_Hugetlb, Swap, SwapPss, KernelPageSize,
- * MMUPageSize, Locked, VmFlags */
- else if (sub_version == 3)
- ret = 17;
- /* Vma, Size, Rss, Pss, Shared_Clean, Shard_Dirty,
- * Private_Clean, Private_Drity,
- * Referenced, Anonymous, AnonHugePages, Swap, SwapPss,
- * KernelPageSize, MMUPageSize, Locked, VmFlags */
- else
- ret = 16;
- /* Vma, Size, Rss, Pss, Shared_Clean, Shard_Dirty,
- * Private_Clean, Private_Drity,
- * Referenced, Anonymous, AnonHugePages, Swap,
- * KernelPageSize, MMUPageSize, Locked, VmFlags */
- } else if (buf.release[0] == '3') {
- if (sub_version >= 10)
- ret = 16;
- /* Vma, Size, Rss, Pss, Shared_Clean, Shard_Dirty,
- * Private_Clean, Private_Drity,
- * Referenced, Anonymous, AnonHugePages, Swap,
- * KernelPageSize, MMUPageSize, Locked, VmFlags */
- else
- ret = 15;
- /* Vma, Size, Rss, Pss, Shared_Clean, Shard_Dirty,
- * Private_Clean, Private_Drity,
- * Referenced, Anonymous, AnonHugePages, Swap,
- * KernelPageSize, MMUPageSize, Locked */
- } else {
- ret = 12;
- /* Vma, Size, Rss, Pss, Shared_Clean, Shard_Dirty,
- * Private_Clean, Private_Drity,
- * Referenced, Swap, KernelPageSize, MMUPageSize */
- }
- }
- return ret;
-}
-
-int get_smaps_lcnt(void)
-{
- char *buf, *buf_start, *line;
- char cmd[64] = "/proc/self/smaps";
- int line_count = 0;
- long start_addr, end_addr;
- unsigned long pg_off;
- int major, minor;
- char flags[4];
-
- buf_start = cread(cmd);
- if (buf_start == NULL) {
- goto error;
- }
-
- buf = buf_start;
- if ((line = cgets(&buf)) == 0)
- goto error;
-
- if (sscanf(line, "%lx-%lx %s %lx %x:%x",
- &start_addr, &end_addr, flags, &pg_off, &major, &minor) != 6) {
- goto error;
- }
-
- while ((line = cgets(&buf)) != 0 ) {
- line_count++;
- if (sscanf(line, "%lx-%lx %s %lx %x:%x",
- &start_addr, &end_addr, flags, &pg_off, &major, &minor) == 6)
- break;
- }
-
- return line_count;
-
-error:
- return get_fixed_smaps_lcnt();
-}
-
int main(int argc, char *argv[])
{
int usage = 1;
sum = 0;
if (argc > 1) {
- smaps_lcnt = get_smaps_lcnt();
-
if (!strncmp(argv[1], "-r", strlen("-r")+1)) {
if (argc >= 3)
show_rss(OUTPUT_FILE, argv[2]);