1824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm/* libunwind - a platform-independent unwind library
264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm   Copyright (C) 2003-2004 Hewlett-Packard Co
303e05b41386fd5797cb8cd62eff7f0ba77c4e07eDavid Mosberger-Tang   Copyright (C) 2007 David Mosberger-Tang
403e05b41386fd5797cb8cd62eff7f0ba77c4e07eDavid Mosberger-Tang	Contributed by David Mosberger-Tang <dmosberger@gmail.com>
5824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
6824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmThis file is part of libunwind.
7824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
8824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmPermission is hereby granted, free of charge, to any person obtaining
9824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidma copy of this software and associated documentation files (the
10824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm"Software"), to deal in the Software without restriction, including
11824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmwithout limitation the rights to use, copy, modify, merge, publish,
12824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmdistribute, sublicense, and/or sell copies of the Software, and to
13824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmpermit persons to whom the Software is furnished to do so, subject to
14824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmthe following conditions:
15824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
16824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmThe above copyright notice and this permission notice shall be
17824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmincluded in all copies or substantial portions of the Software.
18824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
19824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
26824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
27824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm#ifndef os_linux_h
28824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm#define os_linux_h
29824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
307d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris#include <sys/mman.h>
317d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris
32824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmstruct map_iterator
33824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm  {
3464c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    off_t offset;
3564c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    int fd;
365de4b351e7624889db611e10dd3034e0176db5eemostang.com!davidm    size_t buf_size;
375de4b351e7624889db611e10dd3034e0176db5eemostang.com!davidm    char *buf;
385de4b351e7624889db611e10dd3034e0176db5eemostang.com!davidm    char *buf_end;
39b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov    char *path;
40824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm  };
41824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
4264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidmstatic inline char *
4364c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidmltoa (char *buf, long val)
4464c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm{
4564c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  char *cp = buf, tmp;
4664c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  ssize_t i, len;
4764c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
4864c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  do
4964c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    {
5064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      *cp++ = '0' + (val % 10);
5164c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      val /= 10;
5264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    }
5364c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  while (val);
5464c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
5564c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  /* reverse the order of the digits: */
5664c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  len = cp - buf;
5764c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  --cp;
5864c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  for (i = 0; i < len / 2; ++i)
5964c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    {
6064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      tmp = buf[i];
6164c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      buf[i] = cp[-i];
6264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      cp[-i] = tmp;
6364c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    }
6464c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  return buf + len;
6564c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm}
6664c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
67b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikovstatic inline int
68824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmmaps_init (struct map_iterator *mi, pid_t pid)
69824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm{
70b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov  char path[sizeof ("/proc/0123456789/maps")], *cp;
71824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
7264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  memcpy (path, "/proc/", 6);
7364c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  cp = ltoa (path + 6, pid);
74b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov  assert (cp + 6 < path + sizeof (path));
7564c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  memcpy (cp, "/maps", 6);
7664c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
7764c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  mi->fd = open (path, O_RDONLY);
782f210753bd631692bd93f4d0a90e9195424075b9mostang.com!davidm  if (mi->fd >= 0)
792f210753bd631692bd93f4d0a90e9195424075b9mostang.com!davidm    {
80b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov      /* Try to allocate a page-sized buffer.  */
812f210753bd631692bd93f4d0a90e9195424075b9mostang.com!davidm      mi->buf_size = getpagesize ();
82890e23eb9d3ffd9be2a025189a21794b5ed0e0ffTommi Rantala      cp = mmap (NULL, mi->buf_size, PROT_READ | PROT_WRITE,
832f210753bd631692bd93f4d0a90e9195424075b9mostang.com!davidm		 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
842f210753bd631692bd93f4d0a90e9195424075b9mostang.com!davidm      if (cp == MAP_FAILED)
856a072982ddd0b8c1597ac2aa17559732c8b5e763Zachary T Welch	{
866a072982ddd0b8c1597ac2aa17559732c8b5e763Zachary T Welch	  close(mi->fd);
876a072982ddd0b8c1597ac2aa17559732c8b5e763Zachary T Welch	  mi->fd = -1;
886a072982ddd0b8c1597ac2aa17559732c8b5e763Zachary T Welch	  return -1;
896a072982ddd0b8c1597ac2aa17559732c8b5e763Zachary T Welch	}
902f210753bd631692bd93f4d0a90e9195424075b9mostang.com!davidm      else
91b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	{
92b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	  mi->offset = 0;
93b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	  mi->buf = mi->buf_end = cp + mi->buf_size;
94b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	  return 0;
95b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	}
962f210753bd631692bd93f4d0a90e9195424075b9mostang.com!davidm    }
97b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov  return -1;
9864c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm}
9964c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
10064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidmstatic inline char *
10164c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidmskip_whitespace (char *cp)
10264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm{
10364c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  if (!cp)
10464c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    return NULL;
10564c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
10664c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  while (*cp == ' ' || *cp == '\t')
10764c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    ++cp;
10864c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  return cp;
10964c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm}
11064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
11164c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidmstatic inline char *
11264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidmscan_hex (char *cp, unsigned long *valp)
11364c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm{
11464c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  unsigned long num_digits = 0, digit, val = 0;
11564c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
11664c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  cp = skip_whitespace (cp);
11764c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  if (!cp)
11864c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    return NULL;
11964c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
12064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  while (1)
12164c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    {
12264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      digit = *cp;
12364c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      if ((digit - '0') <= 9)
12464c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm	digit -= '0';
12564c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      else if ((digit - 'a') < 6)
12664c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm	digit -= 'a' - 10;
12764c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      else if ((digit - 'A') < 6)
12864c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm	digit -= 'A' - 10;
12964c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      else
13064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm	break;
13164c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      val = (val << 4) | digit;
13264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      ++num_digits;
13364c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      ++cp;
13464c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    }
13564c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  if (!num_digits)
13664c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    return NULL;
13764c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  *valp = val;
13864c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  return cp;
13964c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm}
14064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
14164c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidmstatic inline char *
14264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidmscan_dec (char *cp, unsigned long *valp)
14364c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm{
14464c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  unsigned long num_digits = 0, digit, val = 0;
14564c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
14664c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  if (!(cp = skip_whitespace (cp)))
14764c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    return NULL;
14864c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
14964c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  while (1)
15064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    {
1516c61288b9c5b3c967937d9ab12113bc7e368e433hp.com!davidm      digit = *cp;
15264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      if ((digit - '0') <= 9)
1536c61288b9c5b3c967937d9ab12113bc7e368e433hp.com!davidm	{
1546c61288b9c5b3c967937d9ab12113bc7e368e433hp.com!davidm	  digit -= '0';
1556c61288b9c5b3c967937d9ab12113bc7e368e433hp.com!davidm	  ++cp;
1566c61288b9c5b3c967937d9ab12113bc7e368e433hp.com!davidm	}
15764c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      else
15864c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm	break;
15964c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      val = (10 * val) + digit;
16064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      ++num_digits;
16164c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    }
16264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  if (!num_digits)
16364c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    return NULL;
16464c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  *valp = val;
16564c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  return cp;
16664c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm}
16764c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
16864c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidmstatic inline char *
16964c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidmscan_char (char *cp, char *valp)
17064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm{
17164c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  if (!cp)
17264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    return NULL;
17364c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
1746c61288b9c5b3c967937d9ab12113bc7e368e433hp.com!davidm  *valp = *cp;
1756c61288b9c5b3c967937d9ab12113bc7e368e433hp.com!davidm
1766c61288b9c5b3c967937d9ab12113bc7e368e433hp.com!davidm  /* don't step over NUL terminator */
1776c61288b9c5b3c967937d9ab12113bc7e368e433hp.com!davidm  if (*cp)
1786c61288b9c5b3c967937d9ab12113bc7e368e433hp.com!davidm    ++cp;
17964c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  return cp;
18064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm}
18164c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
18264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm/* Scan a string delimited by white-space.  Fails on empty string or
18364c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm   if string is doesn't fit in the specified buffer.  */
18464c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidmstatic inline char *
18564c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidmscan_string (char *cp, char *valp, size_t buf_size)
18664c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm{
18764c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  size_t i = 0;
18864c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
18964c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  if (!(cp = skip_whitespace (cp)))
19064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    return NULL;
19164c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
19264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  while (*cp != ' ' && *cp != '\t' && *cp != '\0')
19364c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    {
194b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov      if ((valp != NULL) && (i < buf_size - 1))
19564c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm	valp[i++] = *cp;
19664c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      ++cp;
19764c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    }
19864c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  if (i == 0 || i >= buf_size)
19964c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm    return NULL;
20064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  valp[i] = '\0';
20164c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  return cp;
202824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm}
203824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
204824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmstatic inline int
205824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmmaps_next (struct map_iterator *mi,
2067d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris	   unsigned long *low, unsigned long *high, unsigned long *offset,
2077d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris	   unsigned long *flags)
208824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm{
209851f14281c2fefb596c8e6b2e356c553a3f5cc87Arun Sharma  char perm[16], dash = 0, colon = 0, *cp;
21064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  unsigned long major, minor, inum;
21164c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  ssize_t i, nread;
212824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
21364c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  if (mi->fd < 0)
214824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm    return 0;
215824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
21664c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  while (1)
217824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm    {
218b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov      ssize_t bytes_left = mi->buf_end - mi->buf;
219b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov      char *eol = NULL;
2205de4b351e7624889db611e10dd3034e0176db5eemostang.com!davidm
221b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov      for (i = 0; i < bytes_left; ++i)
222b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	{
223b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	  if (mi->buf[i] == '\n')
2245de4b351e7624889db611e10dd3034e0176db5eemostang.com!davidm	    {
225b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	      eol = mi->buf + i;
226b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	      break;
2275de4b351e7624889db611e10dd3034e0176db5eemostang.com!davidm	    }
228b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	  else if (mi->buf[i] == '\0')
229b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	    break;
23064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm	}
231b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov      if (!eol)
23264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm	{
233b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	  /* copy down the remaining bytes, if any */
234b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	  if (bytes_left > 0)
235b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	    memmove (mi->buf_end - mi->buf_size, mi->buf, bytes_left);
236b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov
237b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	  mi->buf = mi->buf_end - mi->buf_size;
238b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	  nread = read (mi->fd, mi->buf + bytes_left,
239b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov			mi->buf_size - bytes_left);
240b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	  if (nread <= 0)
2415de4b351e7624889db611e10dd3034e0176db5eemostang.com!davidm	    return 0;
242b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	  else if ((size_t) (nread + bytes_left) < mi->buf_size)
2435de4b351e7624889db611e10dd3034e0176db5eemostang.com!davidm	    {
244b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	      /* Move contents to the end of the buffer so we
245b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov		 maintain the invariant that all bytes between
246b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov		 mi->buf and mi->buf_end are valid.  */
247b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	      memmove (mi->buf_end - nread - bytes_left, mi->buf,
248b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov		       nread + bytes_left);
249b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	      mi->buf = mi->buf_end - nread - bytes_left;
2505de4b351e7624889db611e10dd3034e0176db5eemostang.com!davidm	    }
251b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov
252b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	  eol = mi->buf + bytes_left + nread - 1;
253b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov
254b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	  for (i = bytes_left; i < bytes_left + nread; ++i)
255b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	    if (mi->buf[i] == '\n')
256b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	      {
257b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov		eol = mi->buf + i;
258b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov		break;
259b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	      }
26064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm	}
261b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov      cp = mi->buf;
262b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov      mi->buf = eol + 1;
263b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov      *eol = '\0';
26464c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm
26564c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      /* scan: "LOW-HIGH PERM OFFSET MAJOR:MINOR INUM PATH" */
2665de4b351e7624889db611e10dd3034e0176db5eemostang.com!davidm      cp = scan_hex (cp, low);
26764c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      cp = scan_char (cp, &dash);
26864c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      cp = scan_hex (cp, high);
26964c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      cp = scan_string (cp, perm, sizeof (perm));
27064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      cp = scan_hex (cp, offset);
27164c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      cp = scan_hex (cp, &major);
27264c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      cp = scan_char (cp, &colon);
27364c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      cp = scan_hex (cp, &minor);
27464c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      cp = scan_dec (cp, &inum);
275b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov      cp = mi->path = skip_whitespace (cp);
276b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov      if (!cp)
277b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov	continue;
278b56375e76a0e23b6e464d994bc6a790e086b91dbPaul Pluzhnikov      cp = scan_string (cp, NULL, 0);
2795a1d3c6fd765e45b97f478c9db3a2d4cdaa75c69Arun Sharma      if (dash != '-' || colon != ':')
28064c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm	continue;	/* skip line with unknown or bad format */
2817d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris      if (flags)
2827d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris        {
2837d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris          *flags = 0;
2847d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris          if (perm[0] == 'r')
2857d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris            {
2867d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris              *flags |= PROT_READ;
2877d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris            }
2887d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris          if (perm[1] == 'w')
2897d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris            {
2907d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris              *flags |= PROT_WRITE;
2917d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris            }
2927d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris          if (perm[2] == 'x')
2937d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris            {
2947d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris              *flags |= PROT_EXEC;
2957d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris            }
2967d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris        }
29764c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm      return 1;
298824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm    }
299824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm  return 0;
300824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm}
301824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
302824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmstatic inline void
303824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidmmaps_close (struct map_iterator *mi)
304824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm{
30564c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  if (mi->fd < 0)
306cfded02a05f7fd5314ca4619b53005955a60aceehp.com!davidm    return;
30764c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  close (mi->fd);
30864c702cea7c2de53ff1ff93dfe76e065036b4e3emostang.com!davidm  mi->fd = -1;
3092f210753bd631692bd93f4d0a90e9195424075b9mostang.com!davidm  if (mi->buf)
3102f210753bd631692bd93f4d0a90e9195424075b9mostang.com!davidm    {
3112f210753bd631692bd93f4d0a90e9195424075b9mostang.com!davidm      munmap (mi->buf_end - mi->buf_size, mi->buf_size);
312890e23eb9d3ffd9be2a025189a21794b5ed0e0ffTommi Rantala      mi->buf = mi->buf_end = NULL;
3132f210753bd631692bd93f4d0a90e9195424075b9mostang.com!davidm    }
314824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm}
315824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm
316824d6619b500a86ff2fc680268357f0215d59b0cmostang.com!davidm#endif /* os_linux_h */
317