LKML Archive on lore.kernel.org
 help / color / Atom feed
* [RFC PATCH 0/2] Add basic support for PE binary format
@ 2020-06-01 11:19 Rémi Bernon
  2020-06-01 11:19 ` [RFC PATCH 1/2] perf dso: Use libbfd to read build_id and .gnu_debuglink section Rémi Bernon
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Rémi Bernon @ 2020-06-01 11:19 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo
  Cc: Rémi Bernon

Hi,

I'm currently trying to improve compatibility between Wine and perf, and
I would like to have you opinion on this approach.

The main problem is that Wine uses PE binary format for most of its code
(and of course the Windows application it runs are also using PE binary
format), and perf is currently unable to parse them to get the symbol
table or even to find the debug file location from build_id or
.gnu_debuglink section.

I know that there's the possibility to use a perfmap file to map address
ranges to symbols, but it requires the runtime to generate it. And in
this case the information is already there in the PE files, just not in
a format that perf supports.

I also have some alternate ways to make it work, using perf-specific
tweaks in Wine for instance. But I believe that having better support of
PE binary format in perf could be generally useful, although for now
Wine is the only use-case I know.

This first starts using libbfd to parse the build_id and .gnu_debuglink
section, to make sure perf gets the debug file location even if the code
modules are in PE binary format.

Then, as Wine also generates debug files in PE or PDB format by default,
it also tries to use libbfd to parse the symbol table from the debug
file if libelf failed.

Of course, advanced features will still lack, but this makes it possible
to have perf report symbols and source-level annotations for any Windows
code running in Wine, assuming the modules aren't stripped.

Cheers,

Rémi Bernon (2):
  perf dso: Use libbfd to read build_id and .gnu_debuglink section
  perf symbols: Try reading the symbol table with libbfd

 tools/perf/util/symbol-elf.c |  65 +++++++++++++++++-
 tools/perf/util/symbol.c     | 124 +++++++++++++++++++++++++++++++++++
 2 files changed, 186 insertions(+), 3 deletions(-)

-- 
2.26.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC PATCH 1/2] perf dso: Use libbfd to read build_id and .gnu_debuglink section
  2020-06-01 11:19 [RFC PATCH 0/2] Add basic support for PE binary format Rémi Bernon
@ 2020-06-01 11:19 ` Rémi Bernon
  2020-06-01 17:48   ` Jiri Olsa
  2020-06-01 11:19 ` [RFC PATCH 2/2] perf symbols: Try reading the symbol table with libbfd Rémi Bernon
  2020-06-01 15:01 ` [RFC PATCH 0/2] Add basic support for PE binary format Arnaldo Carvalho de Melo
  2 siblings, 1 reply; 6+ messages in thread
From: Rémi Bernon @ 2020-06-01 11:19 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo
  Cc: Rémi Bernon, Alexander Shishkin, Jiri Olsa, Mark Rutland,
	Namhyung Kim, Jacek Caban

Wine generates PE binaries for most of its modules and perf is unable
to parse these files to get build_id or .gnu_debuglink section.

Using libbfd when available, instead of libelf, makes it possible to
resolve debug file location regardless of the dso binary format.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Jacek Caban <jacek@codeweavers.com>
---
 tools/perf/util/symbol-elf.c | 65 ++++++++++++++++++++++++++++++++++--
 1 file changed, 62 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index be5b493f8284..85bbc1ec9fe5 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -50,6 +50,10 @@ typedef Elf64_Nhdr GElf_Nhdr;
 #define DMGL_ANSI        (1 << 1)       /* Include const, volatile, etc */
 #endif
 
+#ifdef HAVE_LIBBFD_SUPPORT
+#define PACKAGE 'perf'
+#include <bfd.h>
+#else
 #ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
 extern char *cplus_demangle(const char *, int);
 
@@ -65,9 +69,7 @@ static inline char *bfd_demangle(void __maybe_unused *v,
 {
 	return NULL;
 }
-#else
-#define PACKAGE 'perf'
-#include <bfd.h>
+#endif
 #endif
 #endif
 
@@ -532,6 +534,30 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
 
 int filename__read_build_id(const char *filename, void *bf, size_t size)
 {
+#ifdef HAVE_LIBBFD_SUPPORT
+	int err = -1;
+	bfd *abfd;
+
+	abfd = bfd_openr(filename, NULL);
+	if (!abfd)
+		return -1;
+
+	if (!bfd_check_format(abfd, bfd_object)) {
+		pr_debug2("%s: cannot read %s bfd file.\n", __func__, filename);
+		goto out_close;
+	}
+
+	if (!abfd->build_id || abfd->build_id->size > size)
+		goto out_close;
+
+	memcpy(bf, abfd->build_id->data, abfd->build_id->size);
+	memset(bf + abfd->build_id->size, 0, size - abfd->build_id->size);
+	err = 0;
+
+out_close:
+	bfd_close(abfd);
+	return err;
+#else
 	int fd, err = -1;
 	Elf *elf;
 
@@ -555,6 +581,7 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
 	close(fd);
 out:
 	return err;
+#endif
 }
 
 int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
@@ -611,6 +638,37 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
 int filename__read_debuglink(const char *filename, char *debuglink,
 			     size_t size)
 {
+#ifdef HAVE_LIBBFD_SUPPORT
+	int err = -1;
+	asection *section;
+	bfd *abfd;
+
+	abfd = bfd_openr(filename, NULL);
+	if (!abfd)
+		return -1;
+
+	if (!bfd_check_format(abfd, bfd_object)) {
+		pr_debug2("%s: cannot read %s bfd file.\n", __func__, filename);
+		goto out_close;
+	}
+
+	section = bfd_get_section_by_name(abfd, ".gnu_debuglink");
+	if (!section)
+		goto out_close;
+
+	if (section->size > size)
+		goto out_close;
+
+	if (!bfd_get_section_contents(abfd, section, debuglink, 0,
+				      section->size))
+		goto out_close;
+
+	err = 0;
+
+out_close:
+	bfd_close(abfd);
+	return err;
+#else
 	int fd, err = -1;
 	Elf *elf;
 	GElf_Ehdr ehdr;
@@ -658,6 +716,7 @@ int filename__read_debuglink(const char *filename, char *debuglink,
 	close(fd);
 out:
 	return err;
+#endif
 }
 
 static int dso__swap_init(struct dso *dso, unsigned char eidata)
-- 
2.26.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC PATCH 2/2] perf symbols: Try reading the symbol table with libbfd
  2020-06-01 11:19 [RFC PATCH 0/2] Add basic support for PE binary format Rémi Bernon
  2020-06-01 11:19 ` [RFC PATCH 1/2] perf dso: Use libbfd to read build_id and .gnu_debuglink section Rémi Bernon
@ 2020-06-01 11:19 ` Rémi Bernon
  2020-06-01 17:45   ` Jiri Olsa
  2020-06-01 15:01 ` [RFC PATCH 0/2] Add basic support for PE binary format Arnaldo Carvalho de Melo
  2 siblings, 1 reply; 6+ messages in thread
From: Rémi Bernon @ 2020-06-01 11:19 UTC (permalink / raw)
  To: linux-kernel, Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo
  Cc: Rémi Bernon, Alexander Shishkin, Jiri Olsa, Mark Rutland,
	Namhyung Kim, Jacek Caban

Wine generates PE binaries for its code modules and also generates
debug files in PE or PDB formats, which perf cannot parse either.

Trying libbfd, when supported, if the default libelf symbol parsing
failed, makes it possible to read the symbol table from any binary
format supported by it, and lets perf report symbols and annotations
for Windows applications running under Wine.

Because libbfd doesn't provide symbol size (probably because of some
backends not supporting it), we compute it by first sorting the symbols
by addresses and then considering that they are sequential in a given
section.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Jacek Caban <jacek@codeweavers.com>
---
 tools/perf/util/symbol.c | 124 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 381da6b39f89..0352e97822ac 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1520,6 +1520,121 @@ static int dso__load_perf_map(const char *map_path, struct dso *dso)
 	return -1;
 }
 
+#ifdef HAVE_LIBBFD_SUPPORT
+#define PACKAGE 'perf'
+#include <bfd.h>
+
+static int bfd_symbols__cmpvalue(const void *a, const void *b)
+{
+	const asymbol *as = *(const asymbol **)a, *bs = *(const asymbol **)b;
+
+	if (bfd_asymbol_value(as) != bfd_asymbol_value(bs))
+		return bfd_asymbol_value(as) - bfd_asymbol_value(bs);
+
+	return bfd_asymbol_name(as)[0] - bfd_asymbol_name(bs)[0];
+}
+
+static bool dso__load_bfd_symbols(struct dso *dso, const char *debugfile)
+{
+	bool ret = false;
+	long symbols_size, symbols_count;
+	asection *section;
+	asymbol **symbols, *sym;
+	struct symbol *symbol;
+	bfd *abfd;
+	u_int i;
+	u64 start, len;
+
+	abfd = bfd_openr(dso->long_name, NULL);
+	if (!abfd)
+		return -1;
+
+	if (!bfd_check_format(abfd, bfd_object)) {
+		pr_debug2("%s: cannot read %s bfd file.\n", __func__,
+			  dso->long_name);
+		goto out_close;
+	}
+
+	section = bfd_get_section_by_name(abfd, ".text");
+	if (section)
+		dso->text_offset = section->vma - section->filepos;
+
+	bfd_close(abfd);
+
+	abfd = bfd_openr(debugfile, NULL);
+	if (!abfd)
+		return -1;
+
+	if (!bfd_check_format(abfd, bfd_object)) {
+		pr_debug2("%s: cannot read %s bfd file.\n", __func__,
+			  debugfile);
+		goto out_close;
+	}
+
+	symbols_size = bfd_get_symtab_upper_bound(abfd);
+	if (symbols_size == 0) {
+		bfd_close(abfd);
+		return true;
+	}
+
+	if (symbols_size < 0)
+		goto out_close;
+
+	symbols = malloc(symbols_size);
+	if (!symbols)
+		goto out_close;
+
+	symbols_count = bfd_canonicalize_symtab(abfd, symbols);
+	if (symbols_count < 0)
+		goto out_free;
+
+	qsort(symbols, symbols_count, sizeof(asymbol *), bfd_symbols__cmpvalue);
+
+#ifdef bfd_get_section
+#define bfd_asymbol_section bfd_get_section
+#endif
+	for (i = 0; i < symbols_count; ++i) {
+		sym = symbols[i];
+		section = bfd_asymbol_section(sym);
+		if (!(sym->flags & (BSF_GLOBAL)))
+			continue;
+
+		while (i + 1 < symbols_count &&
+		       bfd_asymbol_section(symbols[i + 1]) == section &&
+		       !(symbols[i + 1]->flags & BSF_GLOBAL))
+			i++;
+
+		if (i + 1 < symbols_count &&
+		    bfd_asymbol_section(symbols[i + 1]) == section)
+			len = symbols[i + 1]->value - sym->value;
+		else
+			len = section->size - sym->value;
+
+		start = bfd_asymbol_value(sym) - dso->text_offset;
+		symbol = symbol__new(start, len, STB_GLOBAL, STT_FUNC,
+				     bfd_asymbol_name(sym));
+		if (!symbol)
+			goto out_free;
+
+		symbols__insert(&dso->symbols, symbol);
+	}
+#ifdef bfd_get_section
+#undef bfd_asymbol_section
+#endif
+
+	symbols__fixup_end(&dso->symbols);
+	symbols__fixup_duplicate(&dso->symbols);
+	dso->adjust_symbols = 1;
+
+	ret = true;
+out_free:
+	free(symbols);
+out_close:
+	bfd_close(abfd);
+	return ret;
+}
+#endif
+
 static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
 					   enum dso_binary_type type)
 {
@@ -1691,6 +1806,7 @@ int dso__load(struct dso *dso, struct map *map)
 		bool next_slot = false;
 		bool is_reg;
 		bool nsexit;
+		bool bfd_syms = false;
 		int sirc = -1;
 
 		enum dso_binary_type symtab_type = binary_type_symtab[i];
@@ -1712,9 +1828,17 @@ int dso__load(struct dso *dso, struct map *map)
 		if (is_reg)
 			sirc = symsrc__init(ss, dso, name, symtab_type);
 
+#ifdef HAVE_LIBBFD_SUPPORT
+		if (is_reg && sirc < 0)
+			bfd_syms = dso__load_bfd_symbols(dso, name);
+#endif
+
 		if (nsexit)
 			nsinfo__mountns_enter(dso->nsinfo, &nsc);
 
+		if (bfd_syms)
+			break;
+
 		if (!is_reg || sirc < 0)
 			continue;
 
-- 
2.26.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC PATCH 0/2] Add basic support for PE binary format
  2020-06-01 11:19 [RFC PATCH 0/2] Add basic support for PE binary format Rémi Bernon
  2020-06-01 11:19 ` [RFC PATCH 1/2] perf dso: Use libbfd to read build_id and .gnu_debuglink section Rémi Bernon
  2020-06-01 11:19 ` [RFC PATCH 2/2] perf symbols: Try reading the symbol table with libbfd Rémi Bernon
@ 2020-06-01 15:01 ` Arnaldo Carvalho de Melo
  2 siblings, 0 replies; 6+ messages in thread
From: Arnaldo Carvalho de Melo @ 2020-06-01 15:01 UTC (permalink / raw)
  To: Rémi Bernon; +Cc: linux-kernel, Peter Zijlstra, Ingo Molnar

Em Mon, Jun 01, 2020 at 01:19:13PM +0200, Rémi Bernon escreveu:
> Hi,
> 
> I'm currently trying to improve compatibility between Wine and perf, and
> I would like to have you opinion on this approach.

Interesting!
 
> The main problem is that Wine uses PE binary format for most of its code
> (and of course the Windows application it runs are also using PE binary
> format), and perf is currently unable to parse them to get the symbol
> table or even to find the debug file location from build_id or
> .gnu_debuglink section.

Unfortunate
 
> I know that there's the possibility to use a perfmap file to map address
> ranges to symbols, but it requires the runtime to generate it. And in
> this case the information is already there in the PE files, just not in
> a format that perf supports.

Right, IMHO the right approach is to abstract away these details and use
whatever PE has to offer.
 
> I also have some alternate ways to make it work, using perf-specific
> tweaks in Wine for instance. But I believe that having better support of
> PE binary format in perf could be generally useful, although for now
> Wine is the only use-case I know.

Agreed.
 
> This first starts using libbfd to parse the build_id and .gnu_debuglink
> section, to make sure perf gets the debug file location even if the code
> modules are in PE binary format.

Right, one thing I'd ask is for you to add to the tree a very simple PE
file, with debug info, a build-id, and then introduce a new 'perf test'
entry that uses the functions you're adding to read and check its
whatever the build-id is there, so that we keep testing this regularly,
please take a look at tools/perf/tests/ to see how to add a new test.
 
> Then, as Wine also generates debug files in PE or PDB format by default,
> it also tries to use libbfd to parse the symbol table from the debug
> file if libelf failed.
> 
> Of course, advanced features will still lack, but this makes it possible
> to have perf report symbols and source-level annotations for any Windows
> code running in Wine, assuming the modules aren't stripped.

Thanks for working on this, right now I'm doing the final touches for
this merge window, but surely I'll get back to this for 5.9, please
remind me if this falls thru the cracks,

- Arnaldo

> Cheers,
> 
> Rémi Bernon (2):
>   perf dso: Use libbfd to read build_id and .gnu_debuglink section
>   perf symbols: Try reading the symbol table with libbfd
> 
>  tools/perf/util/symbol-elf.c |  65 +++++++++++++++++-
>  tools/perf/util/symbol.c     | 124 +++++++++++++++++++++++++++++++++++
>  2 files changed, 186 insertions(+), 3 deletions(-)
> 
> -- 
> 2.26.1
> 

-- 

- Arnaldo

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC PATCH 2/2] perf symbols: Try reading the symbol table with libbfd
  2020-06-01 11:19 ` [RFC PATCH 2/2] perf symbols: Try reading the symbol table with libbfd Rémi Bernon
@ 2020-06-01 17:45   ` Jiri Olsa
  0 siblings, 0 replies; 6+ messages in thread
From: Jiri Olsa @ 2020-06-01 17:45 UTC (permalink / raw)
  To: Rémi Bernon
  Cc: linux-kernel, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Alexander Shishkin, Mark Rutland,
	Namhyung Kim, Jacek Caban

On Mon, Jun 01, 2020 at 01:19:15PM +0200, Rémi Bernon wrote:
> Wine generates PE binaries for its code modules and also generates
> debug files in PE or PDB formats, which perf cannot parse either.
> 
> Trying libbfd, when supported, if the default libelf symbol parsing
> failed, makes it possible to read the symbol table from any binary
> format supported by it, and lets perf report symbols and annotations
> for Windows applications running under Wine.
> 
> Because libbfd doesn't provide symbol size (probably because of some
> backends not supporting it), we compute it by first sorting the symbols
> by addresses and then considering that they are sequential in a given
> section.

hi,
would you have some example for easy test on this?

SNIP

>  static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
>  					   enum dso_binary_type type)
>  {
> @@ -1691,6 +1806,7 @@ int dso__load(struct dso *dso, struct map *map)
>  		bool next_slot = false;
>  		bool is_reg;
>  		bool nsexit;
> +		bool bfd_syms = false;
>  		int sirc = -1;
>  
>  		enum dso_binary_type symtab_type = binary_type_symtab[i];
> @@ -1712,9 +1828,17 @@ int dso__load(struct dso *dso, struct map *map)
>  		if (is_reg)
>  			sirc = symsrc__init(ss, dso, name, symtab_type);
>  
> +#ifdef HAVE_LIBBFD_SUPPORT
> +		if (is_reg && sirc < 0)
> +			bfd_syms = dso__load_bfd_symbols(dso, name);
> +#endif

hum, would it be better to find out is it's PE object
and call it directly instead of the failover?

jirka


> +
>  		if (nsexit)
>  			nsinfo__mountns_enter(dso->nsinfo, &nsc);
>  
> +		if (bfd_syms)
> +			break;
> +
>  		if (!is_reg || sirc < 0)
>  			continue;
>  
> -- 
> 2.26.1
> 


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC PATCH 1/2] perf dso: Use libbfd to read build_id and .gnu_debuglink section
  2020-06-01 11:19 ` [RFC PATCH 1/2] perf dso: Use libbfd to read build_id and .gnu_debuglink section Rémi Bernon
@ 2020-06-01 17:48   ` Jiri Olsa
  0 siblings, 0 replies; 6+ messages in thread
From: Jiri Olsa @ 2020-06-01 17:48 UTC (permalink / raw)
  To: Rémi Bernon
  Cc: linux-kernel, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Alexander Shishkin, Mark Rutland,
	Namhyung Kim, Jacek Caban

On Mon, Jun 01, 2020 at 01:19:14PM +0200, Rémi Bernon wrote:

SNIP

>  int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
> @@ -611,6 +638,37 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
>  int filename__read_debuglink(const char *filename, char *debuglink,
>  			     size_t size)
>  {
> +#ifdef HAVE_LIBBFD_SUPPORT
> +	int err = -1;
> +	asection *section;
> +	bfd *abfd;
> +
> +	abfd = bfd_openr(filename, NULL);
> +	if (!abfd)
> +		return -1;
> +
> +	if (!bfd_check_format(abfd, bfd_object)) {
> +		pr_debug2("%s: cannot read %s bfd file.\n", __func__, filename);
> +		goto out_close;
> +	}
> +
> +	section = bfd_get_section_by_name(abfd, ".gnu_debuglink");
> +	if (!section)
> +		goto out_close;
> +
> +	if (section->size > size)
> +		goto out_close;
> +
> +	if (!bfd_get_section_contents(abfd, section, debuglink, 0,
> +				      section->size))
> +		goto out_close;
> +
> +	err = 0;
> +
> +out_close:
> +	bfd_close(abfd);
> +	return err;
> +#else

please define 2 filename__read_debuglink functions
for each ifdef leg

thanks,
jirka

>  	int fd, err = -1;
>  	Elf *elf;
>  	GElf_Ehdr ehdr;
> @@ -658,6 +716,7 @@ int filename__read_debuglink(const char *filename, char *debuglink,
>  	close(fd);
>  out:
>  	return err;
> +#endif
>  }
>  
>  static int dso__swap_init(struct dso *dso, unsigned char eidata)
> -- 
> 2.26.1
> 


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, back to index

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-01 11:19 [RFC PATCH 0/2] Add basic support for PE binary format Rémi Bernon
2020-06-01 11:19 ` [RFC PATCH 1/2] perf dso: Use libbfd to read build_id and .gnu_debuglink section Rémi Bernon
2020-06-01 17:48   ` Jiri Olsa
2020-06-01 11:19 ` [RFC PATCH 2/2] perf symbols: Try reading the symbol table with libbfd Rémi Bernon
2020-06-01 17:45   ` Jiri Olsa
2020-06-01 15:01 ` [RFC PATCH 0/2] Add basic support for PE binary format Arnaldo Carvalho de Melo

LKML Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lkml.kernel.org/lkml/0 lkml/git/0.git
	git clone --mirror https://lkml.kernel.org/lkml/1 lkml/git/1.git
	git clone --mirror https://lkml.kernel.org/lkml/2 lkml/git/2.git
	git clone --mirror https://lkml.kernel.org/lkml/3 lkml/git/3.git
	git clone --mirror https://lkml.kernel.org/lkml/4 lkml/git/4.git
	git clone --mirror https://lkml.kernel.org/lkml/5 lkml/git/5.git
	git clone --mirror https://lkml.kernel.org/lkml/6 lkml/git/6.git
	git clone --mirror https://lkml.kernel.org/lkml/7 lkml/git/7.git
	git clone --mirror https://lkml.kernel.org/lkml/8 lkml/git/8.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 lkml lkml/ https://lkml.kernel.org/lkml \
		linux-kernel@vger.kernel.org
	public-inbox-index lkml

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-kernel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git