⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dl-profile.c

📁 Newlib 嵌入式 C库 标准实现代码
💻 C
📖 第 1 页 / 共 2 页
字号:
      char buf[400];      _dl_error_printf ("%s: cannot open file: %s\n", filename,			__strerror_r (errno, buf, sizeof buf));      return;    }  if (fstat64 (fd, &st) < 0 || !S_ISREG (st.st_mode))    {      /* Not stat'able or not a regular file => don't use it.  */      char buf[400];      int errnum = errno;      __close (fd);      _dl_error_printf ("%s: cannot stat file: %s\n", filename,			__strerror_r (errnum, buf, sizeof buf));      return;    }  /* Test the size.  If it does not match what we expect from the size     values in the map MAP we don't use it and warn the user.  */  if (st.st_size == 0)    {      /* We have to create the file.  */      char buf[_dl_pagesize];      memset (buf, '\0', _dl_pagesize);      if (__lseek (fd, expected_size & ~(_dl_pagesize - 1), SEEK_SET) == -1)	{	  char buf[400];	  int errnum;	cannot_create:	  errnum = errno;	  __close (fd);	  _dl_error_printf ("%s: cannot create file: %s\n", filename,			    __strerror_r (errnum, buf, sizeof buf));	  return;	}      if (TEMP_FAILURE_RETRY (__libc_write (fd, buf, (expected_size						      & (_dl_pagesize - 1))))	  < 0)	goto cannot_create;    }  else if (st.st_size != expected_size)    {      __close (fd);    wrong_format:      if (addr != NULL)	__munmap ((void *) addr, expected_size);      _dl_error_printf ("%s: file is no correct profile data file for `%s'\n",			filename, _dl_profile);      return;    }  addr = (struct gmon_hdr *) __mmap (NULL, expected_size, PROT_READ|PROT_WRITE,				     MAP_SHARED|MAP_FILE, fd, 0);  if (addr == (struct gmon_hdr *) MAP_FAILED)    {      char buf[400];      int errnum = errno;      __close (fd);      _dl_error_printf ("%s: cannot map file: %s\n", filename,			__strerror_r (errnum, buf, sizeof buf));      return;    }  /* We don't need the file desriptor anymore.  */  __close (fd);  /* Pointer to data after the header.  */  hist = (char *) (addr + 1);  kcount = (uint16_t *) ((char *) hist + sizeof (uint32_t)			 + sizeof (struct gmon_hist_hdr));  /* Compute pointer to array of the arc information.  */  narcsp = (uint32_t *) ((char *) kcount + kcountsize + sizeof (uint32_t));  data = (struct here_cg_arc_record *) ((char *) narcsp + sizeof (uint32_t));  if (st.st_size == 0)    {      /* Create the signature.  */      memcpy (addr, &gmon_hdr, sizeof (struct gmon_hdr));      *(uint32_t *) hist = GMON_TAG_TIME_HIST;      memcpy (hist + sizeof (uint32_t), &hist_hdr,	      sizeof (struct gmon_hist_hdr));      narcsp[-1] = GMON_TAG_CG_ARC;    }  else    {      /* Test the signature in the file.  */      if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0	  || *(uint32_t *) hist != GMON_TAG_TIME_HIST	  || memcmp (hist + sizeof (uint32_t), &hist_hdr,		     sizeof (struct gmon_hist_hdr)) != 0	  || narcsp[-1] != GMON_TAG_CG_ARC)	goto wrong_format;    }  /* Allocate memory for the froms data and the pointer to the tos records.  */  tos = (uint16_t *) calloc (tossize + fromssize, 1);  if (tos == NULL)    {      __munmap ((void *) addr, expected_size);      _dl_fatal_printf ("Out of memory while initializing profiler\n");      /* NOTREACHED */    }  froms = (struct here_fromstruct *) ((char *) tos + tossize);  fromidx = 0;  /* Now we have to process all the arc count entries.  BTW: it is     not critical whether the *NARCSP value changes meanwhile.  Before     we enter a new entry in to toset we will check that everything is     available in TOS.  This happens in _dl_mcount.     Loading the entries in reverse order should help to get the most     frequently used entries at the front of the list.  */  for (idx = narcs = MIN (*narcsp, fromlimit); idx > 0; )    {      size_t to_index;      size_t newfromidx;      --idx;      to_index = (data[idx].self_pc / (hashfraction * sizeof (*tos)));      newfromidx = fromidx++;      froms[newfromidx].here = &data[idx];      froms[newfromidx].link = tos[to_index];      tos[to_index] = newfromidx;    }  /* Setup counting data.  */  if (kcountsize < highpc - lowpc)    {#if 0      s_scale = ((double) kcountsize / (highpc - lowpc)) * SCALE_1_TO_1;#else      size_t range = highpc - lowpc;      size_t quot = range / kcountsize;      if (quot >= SCALE_1_TO_1)	s_scale = 1;      else if (quot >= SCALE_1_TO_1 / 256)	s_scale = SCALE_1_TO_1 / quot;      else if (range > ULONG_MAX / 256)	s_scale = (SCALE_1_TO_1 * 256) / (range / (kcountsize / 256));      else	s_scale = (SCALE_1_TO_1 * 256) / ((range * 256) / kcountsize);#endif    }  else    s_scale = SCALE_1_TO_1;  /* Start the profiler.  */  profil ((void *) kcount, kcountsize, lowpc, s_scale);  /* Turn on profiling.  */  running = 1;}void_dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc){  volatile uint16_t *topcindex;  size_t i, fromindex;  struct here_fromstruct *fromp;  if (! running)    return;  /* Compute relative addresses.  The shared object can be loaded at     any address.  The value of frompc could be anything.  We cannot     restrict it in any way, just set to a fixed value (0) in case it     is outside the allowed range.  These calls show up as calls from     <external> in the gprof output.  */  frompc -= lowpc;  if (frompc >= textsize)    frompc = 0;  selfpc -= lowpc;  if (selfpc >= textsize)    goto done;  /* Getting here we now have to find out whether the location was     already used.  If yes we are lucky and only have to increment a     counter (this also has to be atomic).  If the entry is new things     are getting complicated...  */  /* Avoid integer divide if possible.  */  if ((HASHFRACTION & (HASHFRACTION - 1)) == 0)    i = selfpc >> log_hashfraction;  else    i = selfpc / (hashfraction * sizeof (*tos));  topcindex = &tos[i];  fromindex = *topcindex;  if (fromindex == 0)    goto check_new_or_add;  fromp = &froms[fromindex];  /* We have to look through the chain of arcs whether there is already     an entry for our arc.  */  while (fromp->here->from_pc != frompc)    {      if (fromp->link != 0)	do	  fromp = &froms[fromp->link];	while (fromp->link != 0 && fromp->here->from_pc != frompc);      if (fromp->here->from_pc != frompc)	{	  topcindex = &fromp->link;	check_new_or_add:	  /* Our entry is not among the entries we read so far from the	     data file.  Now see whether we have to update the list.  */	  while (narcs != *narcsp && narcs < fromlimit)	    {	      size_t to_index;	      size_t newfromidx;	      to_index = (data[narcs].self_pc			  / (hashfraction * sizeof (*tos)));	      newfromidx = exchange_and_add (&fromidx, 1) + 1;	      froms[newfromidx].here = &data[narcs];	      froms[newfromidx].link = tos[to_index];	      tos[to_index] = newfromidx;	      atomic_add (&narcs, 1);	    }	  /* If we still have no entry stop searching and insert.  */	  if (*topcindex == 0)	    {	      uint32_t newarc = exchange_and_add (narcsp, 1);	      /* In rare cases it could happen that all entries in FROMS are		 occupied.  So we cannot count this anymore.  */	      if (newarc >= fromlimit)		goto done;	      *topcindex = exchange_and_add (&fromidx, 1) + 1;	      fromp = &froms[*topcindex];	      fromp->here = &data[newarc];	      data[newarc].from_pc = frompc;	      data[newarc].self_pc = selfpc;	      data[newarc].count = 0;	      fromp->link = 0;	      atomic_add (&narcs, 1);	      break;	    }	  fromp = &froms[*topcindex];	}      else	/* Found in.  */	break;    }  /* Increment the counter.  */  atomic_add (&fromp->here->count, 1); done:  ;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -