PageRenderTime 140ms CodeModel.GetById 17ms app.highlight 87ms RepoModel.GetById 1ms app.codeStats 0ms

/tools/perf/util/probe-event.c

https://bitbucket.org/abioy/linux
C | 802 lines | 630 code | 102 blank | 70 comment | 164 complexity | 1e9d38018fec080973315c4cc8aab651 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, GPL-2.0, LGPL-2.0, AGPL-1.0
  1/*
  2 * probe-event.c : perf-probe definition to kprobe_events format converter
  3 *
  4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
  5 *
  6 * This program is free software; you can redistribute it and/or modify
  7 * it under the terms of the GNU General Public License as published by
  8 * the Free Software Foundation; either version 2 of the License, or
  9 * (at your option) any later version.
 10 *
 11 * This program is distributed in the hope that it will be useful,
 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14 * GNU General Public License for more details.
 15 *
 16 * You should have received a copy of the GNU General Public License
 17 * along with this program; if not, write to the Free Software
 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 19 *
 20 */
 21
 22#define _GNU_SOURCE
 23#include <sys/utsname.h>
 24#include <sys/types.h>
 25#include <sys/stat.h>
 26#include <fcntl.h>
 27#include <errno.h>
 28#include <stdio.h>
 29#include <unistd.h>
 30#include <stdlib.h>
 31#include <string.h>
 32#include <stdarg.h>
 33#include <limits.h>
 34
 35#undef _GNU_SOURCE
 36#include "event.h"
 37#include "string.h"
 38#include "strlist.h"
 39#include "debug.h"
 40#include "cache.h"
 41#include "color.h"
 42#include "parse-events.h"  /* For debugfs_path */
 43#include "probe-event.h"
 44
 45#define MAX_CMDLEN 256
 46#define MAX_PROBE_ARGS 128
 47#define PERFPROBE_GROUP "probe"
 48
 49#define semantic_error(msg ...) die("Semantic error :" msg)
 50
 51/* If there is no space to write, returns -E2BIG. */
 52static int e_snprintf(char *str, size_t size, const char *format, ...)
 53	__attribute__((format(printf, 3, 4)));
 54
 55static int e_snprintf(char *str, size_t size, const char *format, ...)
 56{
 57	int ret;
 58	va_list ap;
 59	va_start(ap, format);
 60	ret = vsnprintf(str, size, format, ap);
 61	va_end(ap);
 62	if (ret >= (int)size)
 63		ret = -E2BIG;
 64	return ret;
 65}
 66
 67void parse_line_range_desc(const char *arg, struct line_range *lr)
 68{
 69	const char *ptr;
 70	char *tmp;
 71	/*
 72	 * <Syntax>
 73	 * SRC:SLN[+NUM|-ELN]
 74	 * FUNC[:SLN[+NUM|-ELN]]
 75	 */
 76	ptr = strchr(arg, ':');
 77	if (ptr) {
 78		lr->start = (unsigned int)strtoul(ptr + 1, &tmp, 0);
 79		if (*tmp == '+')
 80			lr->end = lr->start + (unsigned int)strtoul(tmp + 1,
 81								    &tmp, 0);
 82		else if (*tmp == '-')
 83			lr->end = (unsigned int)strtoul(tmp + 1, &tmp, 0);
 84		else
 85			lr->end = 0;
 86		pr_debug("Line range is %u to %u\n", lr->start, lr->end);
 87		if (lr->end && lr->start > lr->end)
 88			semantic_error("Start line must be smaller"
 89				       " than end line.");
 90		if (*tmp != '\0')
 91			semantic_error("Tailing with invalid character '%d'.",
 92				       *tmp);
 93		tmp = strndup(arg, (ptr - arg));
 94	} else
 95		tmp = strdup(arg);
 96
 97	if (strchr(tmp, '.'))
 98		lr->file = tmp;
 99	else
100		lr->function = tmp;
101}
102
103/* Check the name is good for event/group */
104static bool check_event_name(const char *name)
105{
106	if (!isalpha(*name) && *name != '_')
107		return false;
108	while (*++name != '\0') {
109		if (!isalpha(*name) && !isdigit(*name) && *name != '_')
110			return false;
111	}
112	return true;
113}
114
115/* Parse probepoint definition. */
116static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
117{
118	char *ptr, *tmp;
119	char c, nc = 0;
120	/*
121	 * <Syntax>
122	 * perf probe [EVENT=]SRC[:LN|;PTN]
123	 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
124	 *
125	 * TODO:Group name support
126	 */
127
128	ptr = strpbrk(arg, ";=@+%");
129	if (ptr && *ptr == '=') {	/* Event name */
130		*ptr = '\0';
131		tmp = ptr + 1;
132		ptr = strchr(arg, ':');
133		if (ptr)	/* Group name is not supported yet. */
134			semantic_error("Group name is not supported yet.");
135		if (!check_event_name(arg))
136			semantic_error("%s is bad for event name -it must "
137				       "follow C symbol-naming rule.", arg);
138		pp->event = strdup(arg);
139		arg = tmp;
140	}
141
142	ptr = strpbrk(arg, ";:+@%");
143	if (ptr) {
144		nc = *ptr;
145		*ptr++ = '\0';
146	}
147
148	/* Check arg is function or file and copy it */
149	if (strchr(arg, '.'))	/* File */
150		pp->file = strdup(arg);
151	else			/* Function */
152		pp->function = strdup(arg);
153	DIE_IF(pp->file == NULL && pp->function == NULL);
154
155	/* Parse other options */
156	while (ptr) {
157		arg = ptr;
158		c = nc;
159		if (c == ';') {	/* Lazy pattern must be the last part */
160			pp->lazy_line = strdup(arg);
161			break;
162		}
163		ptr = strpbrk(arg, ";:+@%");
164		if (ptr) {
165			nc = *ptr;
166			*ptr++ = '\0';
167		}
168		switch (c) {
169		case ':':	/* Line number */
170			pp->line = strtoul(arg, &tmp, 0);
171			if (*tmp != '\0')
172				semantic_error("There is non-digit char"
173					       " in line number.");
174			break;
175		case '+':	/* Byte offset from a symbol */
176			pp->offset = strtoul(arg, &tmp, 0);
177			if (*tmp != '\0')
178				semantic_error("There is non-digit character"
179						" in offset.");
180			break;
181		case '@':	/* File name */
182			if (pp->file)
183				semantic_error("SRC@SRC is not allowed.");
184			pp->file = strdup(arg);
185			DIE_IF(pp->file == NULL);
186			break;
187		case '%':	/* Probe places */
188			if (strcmp(arg, "return") == 0) {
189				pp->retprobe = 1;
190			} else	/* Others not supported yet */
191				semantic_error("%%%s is not supported.", arg);
192			break;
193		default:
194			DIE_IF("Program has a bug.");
195			break;
196		}
197	}
198
199	/* Exclusion check */
200	if (pp->lazy_line && pp->line)
201		semantic_error("Lazy pattern can't be used with line number.");
202
203	if (pp->lazy_line && pp->offset)
204		semantic_error("Lazy pattern can't be used with offset.");
205
206	if (pp->line && pp->offset)
207		semantic_error("Offset can't be used with line number.");
208
209	if (!pp->line && !pp->lazy_line && pp->file && !pp->function)
210		semantic_error("File always requires line number or "
211			       "lazy pattern.");
212
213	if (pp->offset && !pp->function)
214		semantic_error("Offset requires an entry function.");
215
216	if (pp->retprobe && !pp->function)
217		semantic_error("Return probe requires an entry function.");
218
219	if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe)
220		semantic_error("Offset/Line/Lazy pattern can't be used with "
221			       "return probe.");
222
223	pr_debug("symbol:%s file:%s line:%d offset:%d return:%d lazy:%s\n",
224		 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
225		 pp->lazy_line);
226}
227
228/* Parse perf-probe event definition */
229void parse_perf_probe_event(const char *str, struct probe_point *pp,
230			    bool *need_dwarf)
231{
232	char **argv;
233	int argc, i;
234
235	*need_dwarf = false;
236
237	argv = argv_split(str, &argc);
238	if (!argv)
239		die("argv_split failed.");
240	if (argc > MAX_PROBE_ARGS + 1)
241		semantic_error("Too many arguments");
242
243	/* Parse probe point */
244	parse_perf_probe_probepoint(argv[0], pp);
245	if (pp->file || pp->line || pp->lazy_line)
246		*need_dwarf = true;
247
248	/* Copy arguments and ensure return probe has no C argument */
249	pp->nr_args = argc - 1;
250	pp->args = zalloc(sizeof(char *) * pp->nr_args);
251	for (i = 0; i < pp->nr_args; i++) {
252		pp->args[i] = strdup(argv[i + 1]);
253		if (!pp->args[i])
254			die("Failed to copy argument.");
255		if (is_c_varname(pp->args[i])) {
256			if (pp->retprobe)
257				semantic_error("You can't specify local"
258						" variable for kretprobe");
259			*need_dwarf = true;
260		}
261	}
262
263	argv_free(argv);
264}
265
266/* Parse kprobe_events event into struct probe_point */
267void parse_trace_kprobe_event(const char *str, struct probe_point *pp)
268{
269	char pr;
270	char *p;
271	int ret, i, argc;
272	char **argv;
273
274	pr_debug("Parsing kprobe_events: %s\n", str);
275	argv = argv_split(str, &argc);
276	if (!argv)
277		die("argv_split failed.");
278	if (argc < 2)
279		semantic_error("Too less arguments.");
280
281	/* Scan event and group name. */
282	ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]",
283		     &pr, (float *)(void *)&pp->group,
284		     (float *)(void *)&pp->event);
285	if (ret != 3)
286		semantic_error("Failed to parse event name: %s", argv[0]);
287	pr_debug("Group:%s Event:%s probe:%c\n", pp->group, pp->event, pr);
288
289	pp->retprobe = (pr == 'r');
290
291	/* Scan function name and offset */
292	ret = sscanf(argv[1], "%a[^+]+%d", (float *)(void *)&pp->function,
293		     &pp->offset);
294	if (ret == 1)
295		pp->offset = 0;
296
297	/* kprobe_events doesn't have this information */
298	pp->line = 0;
299	pp->file = NULL;
300
301	pp->nr_args = argc - 2;
302	pp->args = zalloc(sizeof(char *) * pp->nr_args);
303	for (i = 0; i < pp->nr_args; i++) {
304		p = strchr(argv[i + 2], '=');
305		if (p)	/* We don't need which register is assigned. */
306			*p = '\0';
307		pp->args[i] = strdup(argv[i + 2]);
308		if (!pp->args[i])
309			die("Failed to copy argument.");
310	}
311
312	argv_free(argv);
313}
314
315/* Synthesize only probe point (not argument) */
316int synthesize_perf_probe_point(struct probe_point *pp)
317{
318	char *buf;
319	char offs[64] = "", line[64] = "";
320	int ret;
321
322	pp->probes[0] = buf = zalloc(MAX_CMDLEN);
323	pp->found = 1;
324	if (!buf)
325		die("Failed to allocate memory by zalloc.");
326	if (pp->offset) {
327		ret = e_snprintf(offs, 64, "+%d", pp->offset);
328		if (ret <= 0)
329			goto error;
330	}
331	if (pp->line) {
332		ret = e_snprintf(line, 64, ":%d", pp->line);
333		if (ret <= 0)
334			goto error;
335	}
336
337	if (pp->function)
338		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->function,
339				 offs, pp->retprobe ? "%return" : "", line);
340	else
341		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", pp->file, line);
342	if (ret <= 0) {
343error:
344		free(pp->probes[0]);
345		pp->probes[0] = NULL;
346		pp->found = 0;
347	}
348	return ret;
349}
350
351int synthesize_perf_probe_event(struct probe_point *pp)
352{
353	char *buf;
354	int i, len, ret;
355
356	len = synthesize_perf_probe_point(pp);
357	if (len < 0)
358		return 0;
359
360	buf = pp->probes[0];
361	for (i = 0; i < pp->nr_args; i++) {
362		ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
363				 pp->args[i]);
364		if (ret <= 0)
365			goto error;
366		len += ret;
367	}
368	pp->found = 1;
369
370	return pp->found;
371error:
372	free(pp->probes[0]);
373	pp->probes[0] = NULL;
374
375	return ret;
376}
377
378int synthesize_trace_kprobe_event(struct probe_point *pp)
379{
380	char *buf;
381	int i, len, ret;
382
383	pp->probes[0] = buf = zalloc(MAX_CMDLEN);
384	if (!buf)
385		die("Failed to allocate memory by zalloc.");
386	ret = e_snprintf(buf, MAX_CMDLEN, "%s+%d", pp->function, pp->offset);
387	if (ret <= 0)
388		goto error;
389	len = ret;
390
391	for (i = 0; i < pp->nr_args; i++) {
392		ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
393				 pp->args[i]);
394		if (ret <= 0)
395			goto error;
396		len += ret;
397	}
398	pp->found = 1;
399
400	return pp->found;
401error:
402	free(pp->probes[0]);
403	pp->probes[0] = NULL;
404
405	return ret;
406}
407
408static int open_kprobe_events(int flags, int mode)
409{
410	char buf[PATH_MAX];
411	int ret;
412
413	ret = e_snprintf(buf, PATH_MAX, "%s/../kprobe_events", debugfs_path);
414	if (ret < 0)
415		die("Failed to make kprobe_events path.");
416
417	ret = open(buf, flags, mode);
418	if (ret < 0) {
419		if (errno == ENOENT)
420			die("kprobe_events file does not exist -"
421			    " please rebuild with CONFIG_KPROBE_EVENT.");
422		else
423			die("Could not open kprobe_events file: %s",
424			    strerror(errno));
425	}
426	return ret;
427}
428
429/* Get raw string list of current kprobe_events */
430static struct strlist *get_trace_kprobe_event_rawlist(int fd)
431{
432	int ret, idx;
433	FILE *fp;
434	char buf[MAX_CMDLEN];
435	char *p;
436	struct strlist *sl;
437
438	sl = strlist__new(true, NULL);
439
440	fp = fdopen(dup(fd), "r");
441	while (!feof(fp)) {
442		p = fgets(buf, MAX_CMDLEN, fp);
443		if (!p)
444			break;
445
446		idx = strlen(p) - 1;
447		if (p[idx] == '\n')
448			p[idx] = '\0';
449		ret = strlist__add(sl, buf);
450		if (ret < 0)
451			die("strlist__add failed: %s", strerror(-ret));
452	}
453	fclose(fp);
454
455	return sl;
456}
457
458/* Free and zero clear probe_point */
459static void clear_probe_point(struct probe_point *pp)
460{
461	int i;
462
463	if (pp->event)
464		free(pp->event);
465	if (pp->group)
466		free(pp->group);
467	if (pp->function)
468		free(pp->function);
469	if (pp->file)
470		free(pp->file);
471	if (pp->lazy_line)
472		free(pp->lazy_line);
473	for (i = 0; i < pp->nr_args; i++)
474		free(pp->args[i]);
475	if (pp->args)
476		free(pp->args);
477	for (i = 0; i < pp->found; i++)
478		free(pp->probes[i]);
479	memset(pp, 0, sizeof(*pp));
480}
481
482/* Show an event */
483static void show_perf_probe_event(const char *event, const char *place,
484				  struct probe_point *pp)
485{
486	int i, ret;
487	char buf[128];
488
489	ret = e_snprintf(buf, 128, "%s:%s", pp->group, event);
490	if (ret < 0)
491		die("Failed to copy event: %s", strerror(-ret));
492	printf("  %-40s (on %s", buf, place);
493
494	if (pp->nr_args > 0) {
495		printf(" with");
496		for (i = 0; i < pp->nr_args; i++)
497			printf(" %s", pp->args[i]);
498	}
499	printf(")\n");
500}
501
502/* List up current perf-probe events */
503void show_perf_probe_events(void)
504{
505	int fd;
506	struct probe_point pp;
507	struct strlist *rawlist;
508	struct str_node *ent;
509
510	setup_pager();
511	memset(&pp, 0, sizeof(pp));
512
513	fd = open_kprobe_events(O_RDONLY, 0);
514	rawlist = get_trace_kprobe_event_rawlist(fd);
515	close(fd);
516
517	strlist__for_each(ent, rawlist) {
518		parse_trace_kprobe_event(ent->s, &pp);
519		/* Synthesize only event probe point */
520		synthesize_perf_probe_point(&pp);
521		/* Show an event */
522		show_perf_probe_event(pp.event, pp.probes[0], &pp);
523		clear_probe_point(&pp);
524	}
525
526	strlist__delete(rawlist);
527}
528
529/* Get current perf-probe event names */
530static struct strlist *get_perf_event_names(int fd, bool include_group)
531{
532	char buf[128];
533	struct strlist *sl, *rawlist;
534	struct str_node *ent;
535	struct probe_point pp;
536
537	memset(&pp, 0, sizeof(pp));
538	rawlist = get_trace_kprobe_event_rawlist(fd);
539
540	sl = strlist__new(true, NULL);
541	strlist__for_each(ent, rawlist) {
542		parse_trace_kprobe_event(ent->s, &pp);
543		if (include_group) {
544			if (e_snprintf(buf, 128, "%s:%s", pp.group,
545				       pp.event) < 0)
546				die("Failed to copy group:event name.");
547			strlist__add(sl, buf);
548		} else
549			strlist__add(sl, pp.event);
550		clear_probe_point(&pp);
551	}
552
553	strlist__delete(rawlist);
554
555	return sl;
556}
557
558static void write_trace_kprobe_event(int fd, const char *buf)
559{
560	int ret;
561
562	pr_debug("Writing event: %s\n", buf);
563	ret = write(fd, buf, strlen(buf));
564	if (ret <= 0)
565		die("Failed to write event: %s", strerror(errno));
566}
567
568static void get_new_event_name(char *buf, size_t len, const char *base,
569			       struct strlist *namelist, bool allow_suffix)
570{
571	int i, ret;
572
573	/* Try no suffix */
574	ret = e_snprintf(buf, len, "%s", base);
575	if (ret < 0)
576		die("snprintf() failed: %s", strerror(-ret));
577	if (!strlist__has_entry(namelist, buf))
578		return;
579
580	if (!allow_suffix) {
581		pr_warning("Error: event \"%s\" already exists. "
582			   "(Use -f to force duplicates.)\n", base);
583		die("Can't add new event.");
584	}
585
586	/* Try to add suffix */
587	for (i = 1; i < MAX_EVENT_INDEX; i++) {
588		ret = e_snprintf(buf, len, "%s_%d", base, i);
589		if (ret < 0)
590			die("snprintf() failed: %s", strerror(-ret));
591		if (!strlist__has_entry(namelist, buf))
592			break;
593	}
594	if (i == MAX_EVENT_INDEX)
595		die("Too many events are on the same function.");
596}
597
598void add_trace_kprobe_events(struct probe_point *probes, int nr_probes,
599			     bool force_add)
600{
601	int i, j, fd;
602	struct probe_point *pp;
603	char buf[MAX_CMDLEN];
604	char event[64];
605	struct strlist *namelist;
606	bool allow_suffix;
607
608	fd = open_kprobe_events(O_RDWR, O_APPEND);
609	/* Get current event names */
610	namelist = get_perf_event_names(fd, false);
611
612	for (j = 0; j < nr_probes; j++) {
613		pp = probes + j;
614		if (!pp->event)
615			pp->event = strdup(pp->function);
616		if (!pp->group)
617			pp->group = strdup(PERFPROBE_GROUP);
618		DIE_IF(!pp->event || !pp->group);
619		/* If force_add is true, suffix search is allowed */
620		allow_suffix = force_add;
621		for (i = 0; i < pp->found; i++) {
622			/* Get an unused new event name */
623			get_new_event_name(event, 64, pp->event, namelist,
624					   allow_suffix);
625			snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s\n",
626				 pp->retprobe ? 'r' : 'p',
627				 pp->group, event,
628				 pp->probes[i]);
629			write_trace_kprobe_event(fd, buf);
630			printf("Added new event:\n");
631			/* Get the first parameter (probe-point) */
632			sscanf(pp->probes[i], "%s", buf);
633			show_perf_probe_event(event, buf, pp);
634			/* Add added event name to namelist */
635			strlist__add(namelist, event);
636			/*
637			 * Probes after the first probe which comes from same
638			 * user input are always allowed to add suffix, because
639			 * there might be several addresses corresponding to
640			 * one code line.
641			 */
642			allow_suffix = true;
643		}
644	}
645	/* Show how to use the event. */
646	printf("\nYou can now use it on all perf tools, such as:\n\n");
647	printf("\tperf record -e %s:%s -a sleep 1\n\n", PERFPROBE_GROUP, event);
648
649	strlist__delete(namelist);
650	close(fd);
651}
652
653static void __del_trace_kprobe_event(int fd, struct str_node *ent)
654{
655	char *p;
656	char buf[128];
657
658	/* Convert from perf-probe event to trace-kprobe event */
659	if (e_snprintf(buf, 128, "-:%s", ent->s) < 0)
660		die("Failed to copy event.");
661	p = strchr(buf + 2, ':');
662	if (!p)
663		die("Internal error: %s should have ':' but not.", ent->s);
664	*p = '/';
665
666	write_trace_kprobe_event(fd, buf);
667	printf("Remove event: %s\n", ent->s);
668}
669
670static void del_trace_kprobe_event(int fd, const char *group,
671				   const char *event, struct strlist *namelist)
672{
673	char buf[128];
674	struct str_node *ent, *n;
675	int found = 0;
676
677	if (e_snprintf(buf, 128, "%s:%s", group, event) < 0)
678		die("Failed to copy event.");
679
680	if (strpbrk(buf, "*?")) { /* Glob-exp */
681		strlist__for_each_safe(ent, n, namelist)
682			if (strglobmatch(ent->s, buf)) {
683				found++;
684				__del_trace_kprobe_event(fd, ent);
685				strlist__remove(namelist, ent);
686			}
687	} else {
688		ent = strlist__find(namelist, buf);
689		if (ent) {
690			found++;
691			__del_trace_kprobe_event(fd, ent);
692			strlist__remove(namelist, ent);
693		}
694	}
695	if (found == 0)
696		pr_info("Info: event \"%s\" does not exist, could not remove it.\n", buf);
697}
698
699void del_trace_kprobe_events(struct strlist *dellist)
700{
701	int fd;
702	const char *group, *event;
703	char *p, *str;
704	struct str_node *ent;
705	struct strlist *namelist;
706
707	fd = open_kprobe_events(O_RDWR, O_APPEND);
708	/* Get current event names */
709	namelist = get_perf_event_names(fd, true);
710
711	strlist__for_each(ent, dellist) {
712		str = strdup(ent->s);
713		if (!str)
714			die("Failed to copy event.");
715		pr_debug("Parsing: %s\n", str);
716		p = strchr(str, ':');
717		if (p) {
718			group = str;
719			*p = '\0';
720			event = p + 1;
721		} else {
722			group = "*";
723			event = str;
724		}
725		pr_debug("Group: %s, Event: %s\n", group, event);
726		del_trace_kprobe_event(fd, group, event, namelist);
727		free(str);
728	}
729	strlist__delete(namelist);
730	close(fd);
731}
732
733#define LINEBUF_SIZE 256
734#define NR_ADDITIONAL_LINES 2
735
736static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num)
737{
738	char buf[LINEBUF_SIZE];
739	const char *color = PERF_COLOR_BLUE;
740
741	if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
742		goto error;
743	if (!skip) {
744		if (show_num)
745			fprintf(stdout, "%7u  %s", l, buf);
746		else
747			color_fprintf(stdout, color, "         %s", buf);
748	}
749
750	while (strlen(buf) == LINEBUF_SIZE - 1 &&
751	       buf[LINEBUF_SIZE - 2] != '\n') {
752		if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
753			goto error;
754		if (!skip) {
755			if (show_num)
756				fprintf(stdout, "%s", buf);
757			else
758				color_fprintf(stdout, color, "%s", buf);
759		}
760	}
761	return;
762error:
763	if (feof(fp))
764		die("Source file is shorter than expected.");
765	else
766		die("File read error: %s", strerror(errno));
767}
768
769void show_line_range(struct line_range *lr)
770{
771	unsigned int l = 1;
772	struct line_node *ln;
773	FILE *fp;
774
775	setup_pager();
776
777	if (lr->function)
778		fprintf(stdout, "<%s:%d>\n", lr->function,
779			lr->start - lr->offset);
780	else
781		fprintf(stdout, "<%s:%d>\n", lr->file, lr->start);
782
783	fp = fopen(lr->path, "r");
784	if (fp == NULL)
785		die("Failed to open %s: %s", lr->path, strerror(errno));
786	/* Skip to starting line number */
787	while (l < lr->start)
788		show_one_line(fp, l++, true, false);
789
790	list_for_each_entry(ln, &lr->line_list, list) {
791		while (ln->line > l)
792			show_one_line(fp, (l++) - lr->offset, false, false);
793		show_one_line(fp, (l++) - lr->offset, false, true);
794	}
795
796	if (lr->end == INT_MAX)
797		lr->end = l + NR_ADDITIONAL_LINES;
798	while (l < lr->end && !feof(fp))
799		show_one_line(fp, (l++) - lr->offset, false, false);
800
801	fclose(fp);
802}