LLDB: এই ডিবাগারটি কী, প্রধান কমান্ড এবং iOS ডেভেলপমেন্টে ব্যবহার

লেখক: IT Sectr প্রকাশিত: 2026-05-07 পড়ার সময়: 9 মিনিট

LLDB (Low-Level Debugger) হল LLVM প্রজেক্টের একটি পরবর্তী প্রজন্মের ডিবাগার, যা iOS, macOS, tvOS এবং watchOS-এ অ্যাপ্লিকেশন ডিবাগ করার জন্য Xcode-এ অন্তর্ভুক্ত। GDB-এর বিপরীতে, LLDB LLVM কম্পাইলারের সাথে একটি মডুলার আর্কিটেকচার ব্যবহার করে, যা উচ্চ গতি এবং নির্ভুলতা নিশ্চিত করে। LLVM প্রজেক্ট-এর মতে, LLDB C, Objective-C, C++ এবং Swift-এ ব্রেকপয়েন্ট, ওয়াচপয়েন্ট, মেমরি পরিদর্শন এবং ধাপে ধাপে নির্বাহের সম্পূর্ণ সেট সহ ডিবাগিং সমর্থন করে।

মূল বিষয়

  • LLDB হল LLVM টুলচেইনের উপর ভিত্তি করে ওপেন সোর্স কোড সহ স্ট্যান্ডার্ড Xcode ডিবাগার।
  • মডুলার LLDB আর্কিটেকচার পার্সিং, নির্বাহ এবং ভিজুয়ালাইজেশনের জন্য লাইব্রেরি নিয়ে গঠিত, যা একে অপরের থেকে স্বাধীন।
  • LLDB কমান্ড ব্রেকপয়েন্ট সেট করা, ভেরিয়েবল পরিদর্শন করা, এক্সপ্রেশন নির্বাহ করা এবং ডিবাগিংয়ের সময় অবস্থা পরিবর্তন করতে দেয়।
  • Python API LLDB-তে ডিবাগিং পরিস্থিতি স্বয়ংক্রিয় করতে কাস্টম স্ক্রিপ্ট তৈরি করতে সক্ষম করে।
  • REPL মোড LLDB-তে Swift এবং C কোড নিয়ে পরীক্ষা-নিরীক্ষার জন্য একটি ইন্টারঅ্যাকটিভ পরিবেশ হিসাবে কাজ করে।

LLDB কী এবং এটি কীভাবে কাজ করে

LLDB হল একটি ওপেন-সোর্স ডিবাগার যা LLVM প্রজেক্ট লাইব্রেরির উপর নির্মিত। এটি Xcode 5-এ GDB-কে প্রতিস্থাপন করেছিল এবং তারপর থেকে পুরো Apple ইকোসিস্টেমের জন্য প্রাথমিক ডিবাগিং টুল হয়ে উঠেছে। একচেটিয়া GDB-এর বিপরীতে, LLDB ইন্টারঅ্যাক্টিং লাইব্রেরির একটি সেট হিসাবে প্রয়োগ করা হয়েছে: প্রতিটি ফাংশন — এক্সপ্রেশন পার্সিং থেকে মেমরি ব্যবস্থাপনা পর্যন্ত — একটি পৃথক মডিউলে রাখা হয়েছে, যা রক্ষণাবেক্ষণ এবং সম্প্রসারণকে সহজ করে।

LLDB-এর মূল ক্ষমতার মধ্যে রয়েছে: যেকোনো ধরনের ব্রেকপয়েন্ট সেট করা, ভেরিয়েবল পরিবর্তন ট্র্যাক করার জন্য ওয়াচপয়েন্ট, মেমরি এবং রেজিস্টার পরিদর্শন, ধাপে ধাপে নির্বাহ, থামানো প্রোগ্রামের প্রসঙ্গে নির্বিচারে এক্সপ্রেশন মূল্যায়ন এবং অটোমেশনের জন্য Python স্ক্রিপ্ট চালানো। LLVM রিপোজিটরি অনুসারে, LLDB 200টিরও বেশি ডিবাগ কমান্ড সমর্থন করে এবং DWARF এবং Mach-O ফরম্যাটের — Apple ইকোসিস্টেমের প্রধান ডিবাগ তথ্য ফরম্যাট — সাথে সামঞ্জস্যপূর্ণ।

LLDB-এর একটি গুরুত্বপূর্ণ সুবিধা হল Clang-এর সাথে গভীর একীকরণ। সোর্স কোড পার্স এবং কম্পাইল করার জন্য একই কম্পাইলার ব্যবহার করে, LLDB GDB-তে অনুপলব্ধ নির্ভুলতার সাথে C++ এবং Objective-C এক্সপ্রেশন মূল্যায়ন করতে পারে। Swift ডিবাগিংয়ের জন্য, LLDB একটি পৃথক Swift Language Runtime মডিউল ব্যবহার করে যা ভাষার শব্দার্থ বুঝতে পারে: ঐচ্ছিক প্রকার, প্রোটোকল, জেনেরিক এবং ARC-এর মাধ্যমে মেমরি ব্যবস্থাপনা।

ইতিহাস এবং বিবর্তন

LLDB-এর প্রথম সংস্করণ 2010 সালে LLVM 2.8-এর অংশ হিসাবে আবির্ভূত হয়েছিল। 2013 সালের মধ্যে, এটি Xcode-এ GDB-কে সম্পূর্ণরূপে প্রতিস্থাপন করেছিল। 2019 সালে, Xcode 11 প্রকাশের সাথে, LLDB Swift Error Breakpoints-এর জন্য সমর্থন এবং Swift-এর জন্য উন্নত এক্সপ্রেশন পার্সার পেয়েছিল। Apple-এর মতে, iOS 14 থেকে, সিমুলেটরের জন্য সম্পূর্ণ ডিবাগিং স্ট্যাকও LLDB-এর মাধ্যমে কাজ করে, যা প্ল্যাটফর্মের প্রাথমিক ডিবাগিং টুল হিসাবে এর অবস্থান নিশ্চিত করে।

LLDB আর্কিটেকচার: মডিউল এবং উপাদান

LLDB আর্কিটেকচার মাইক্রোসার্ভিস নীতির উপর নির্মিত: প্রতিটি উপপ্রণালী একটি পৃথক লাইব্রেরি (dylib) হিসাবে বিদ্যমান, একটি সাধারণ API-এর মাধ্যমে অন্যদের সাথে সংযুক্ত। এটি GDB থেকে আলাদা, যেখানে সমস্ত ফাংশন একটি একক বাইনারিতে একত্রিত হয়। মডুলার কাঠামো LLDB উপাদানগুলি স্বাধীনভাবে ব্যবহার করার অনুমতি দেয় — উদাহরণস্বরূপ, এক্সপ্রেশন পার্সারটি সম্পূর্ণ ডিবাগার সংযোগ না করেই IDE-তে এম্বেড করা যেতে পারে।

LLDB উপাদানউদ্দেশ্যলাইব্রেরি
Coreডিবাগ প্রক্রিয়া ব্যবস্থাপনা, ইভেন্ট, থ্রেড অবস্থাliblldbCore.dylib
Expression Parserএক্সপ্রেশন পার্সিং এবং নির্বাহ (C/C++/ObjC/Swift)liblldbExpression.dylib
Symbol FileDWARF, Mach-O, dSYM পড়া — ডিবাগ তথ্য নিয়ে কাজliblldbSymbol.dylib
Target Controlনির্বাহ নিয়ন্ত্রণ: শুরু, থামা, ধাপliblldbTarget.dylib
Interpreterকমান্ড লাইন এবং REPL মোডliblldbInterpreter.dylib

LLDB এবং dSYM ডিবাগ প্রতীক

dSYM হল ডিবাগ তথ্য ফাইল যা Xcode বিল্ডের সময় তৈরি করে। LLDB সেগুলি মেশিন কোডকে সোর্স কোডে ম্যাপ করতে ব্যবহার করে: dSYM ছাড়া, ডিবাগার ফাংশন নাম এবং কোড লাইনের পরিবর্তে শুধুমাত্র মেমরি ঠিকানা দেখায়। App Store অ্যাপ্লিকেশনের জন্য, dSYM ফাইলগুলি Apple সার্ভারে আলাদাভাবে আপলোড করা হয় এবং CrashReporter-এর মাধ্যমে ব্যবহারকারীদের কাছ থেকে প্রাপ্ত ক্র্যাশ লগ প্রতীকী করতে ব্যবহৃত হয়।

lldb
(lldb) target create MyApp.app
(lldb) image list MyApp
MyApp - "/path/to/MyApp.app/MyApp" (arm64)
(lldb) image lookup -n fetchUserData
Address: MyApp[0x1000a3b40] (MyApp.__TEXT.__text + 12352)
Summary: `ViewController.fetchUserData()` at ViewController.swift:42

ডিবাগিংয়ের জন্য মৌলিক LLDB কমান্ড

LLDB কমান্ড বিভিন্ন শ্রেণিতে বিভক্ত: নির্বাহ নিয়ন্ত্রণ, ব্রেকপয়েন্ট ব্যবস্থাপনা, ডেটা পরিদর্শন এবং মেমরি হেরফের। Xcode GUI-এর বিপরীতে, LLDB কনসোল ডিবাগিংয়ের উপর সম্পূর্ণ নিয়ন্ত্রণ দেয় এবং গ্রাফিকাল ইন্টারফেসের মাধ্যমে অনুপলব্ধ অপারেশন অনুমতি দেয় — উদাহরণস্বরূপ, চলাকালীন একটি ভেরিয়েবলের মান পরিবর্তন করা বা ব্রেকপয়েন্ট বাল্ক এডিটিং।

নির্বাহ নিয়ন্ত্রণ কমান্ড

Continue, Step Over, Step Into, Step Out — ডিবাগ চক্রের ভিত্তি। continue পরবর্তী ব্রেকপয়েন্ট পর্যন্ত নির্বাহ পুনরায় শুরু করে। step over বর্তমান লাইনটি সম্পূর্ণরূপে নির্বাহ করে। step into কল করা পদ্ধতির ভিতরে যায়। step out বর্তমান ফাংশনটি সম্পূর্ণ করে এবং কলার কোডে নিয়ন্ত্রণ ফিরিয়ে দেয়। অতিরিক্তভাবে, step with type filter রয়েছে — নির্দিষ্ট ডেটা প্রকার পর্যন্ত ধাপ।

lldb
(lldb) thread backtrace          # কল স্ট্যাক দেখান
* thread #1, queue = 'com.apple.main-thread'
    frame #0: 0x1000a3b40 ViewController`fetchUserData()
    frame #1: 0x1000a2000 ViewController`viewDidLoad()
    frame #2: 0x1a2b345 UIKit`UIViewController.loadView()
(lldb) frame variable          # লোকাল ভেরিয়েবল দেখান
(Int) userId = 42
(String) endpoint = "https://api.example.com/user/42"
(lldb) thread step-over        # Step Over
(lldb) thread step-in          # Step Into

ডেটা পরিদর্শন এবং ফরম্যাটার

LLDB যেকোনো ফরম্যাটে ডেটা দেখার জন্য কমান্ড সরবরাহ করে: memory read, frame variable, target variable। বিশেষ সিনট্যাক্স po (print object) Objective-C অবজেক্টে debugDescription এবং Swift প্রকারে description কল করে। কাস্টম ফরম্যাটার type summary add-এর মাধ্যমে সেট করা হয় — জটিল কাঠামো যেমন CGRect বা IndexPath ডিবাগ করার জন্য দরকারী।

lldb
(lldb) po userProfile           # অবজেক্টের বিবরণ আউটপুট
<UserProfile: 0x600000c4b80>
  - name: "John"
  - age: 30
  - email: "john@example.com"
(lldb) expression userProfile.age = 31    # মান পরিবর্তন করুন
(Int) $R0 = 31
(lldb) memory read 0x600000c4b80 0x600000c4bc0
0x600000c4b80: 6a 6f 68 6e 00 00 00 00 1e 00 00 00 00 00 00 00

এক্সপ্রেশন মূল্যায়ন এবং অবজেক্ট পরিদর্শন

এক্সপ্রেশন মূল্যায়ন LLDB-এর সবচেয়ে শক্তিশালী বৈশিষ্ট্যগুলির মধ্যে একটি, যা GDB-তে তার আধিপত্যের সময় অনুপস্থিত ছিল। LLDB থামানো প্রোগ্রামের প্রসঙ্গে C, Objective-C, C++ এবং Swift-এ নির্বিচারে কোড নির্বাহ করতে পারে, যার মধ্যে পদ্ধতি কল করা, অবজেক্ট তৈরি করা এবং অবস্থা পরিবর্তন করা অন্তর্ভুক্ত। এটি অ্যাপ্লিকেশন পুনরায় চালু এবং পুনরায় কম্পাইল না করেই অনুমান পরীক্ষা করার অনুমতি দেয়।

expression এবং po কমান্ড

expression কমান্ড ডিবাগ করা প্রক্রিয়ার রানটাইমে একটি এক্সপ্রেশন কম্পাইল এবং নির্বাহ করে। -O ফ্ল্যাগ (object description) po ট্রিগার করে। মাল্টি-লাইন এক্সপ্রেশনের জন্য, expression -l Swift -- ব্যবহার করুন। LLDB Clang বা Swift Compiler-এর মাধ্যমে চলাকালীন কোড কম্পাইল করে, ফলাফল বর্তমান প্রসঙ্গে একীভূত করে এবং মান ফেরত দেয়। Apple-এর মতে, জটিলতার উপর নির্ভর করে একটি এক্সপ্রেশন 10–50 ms-এ কম্পাইল হয়।

lldb
(lldb) expr -l Swift -- UIAlertController(title: "Test", message: nil,
  preferredStyle: .alert)
(lldb) expr let $arr = [1, 2, 3].map { $0 * 2 }
(lldb) po $arr3 elements
  - 0 : 2
  - 1 : 4
  - 2 : 6

চলাকালীন অবজেক্ট পরিবর্তন

LLDB শুধু পড়তে নয়, ডিবাগিংয়ের সময় অবজেক্ট এবং ভেরিয়েবলের অবস্থা পরিবর্তন করতেও অনুমতি দেয়। এটি এজ কেস পরীক্ষার জন্য গুরুত্বপূর্ণ: একটি ভেরিয়েবলকে nil-এ সেট করা যেতে পারে, UI উপাদানের রঙ পরিবর্তন করা যেতে পারে, বা সার্ভার প্রতিক্রিয়া সরাসরি ডিবাগারে প্রতিস্থাপন করা যেতে পারে, পুনরায় কম্পাইল এবং পুনরায় চালু না করেই। এই কৌশলটি গেম ডেভেলপমেন্ট এবং দীর্ঘ ফ্লো বিশিষ্ট অ্যাপ্লিকেশনে ব্যাপকভাবে ব্যবহৃত হয়, যেখানে পুনরায় চালু করতে অনেক সময় লাগে।

lldb
(lldb) expr self.label.text = @"Updated"
(lldb) expr -l Swift -- (self as! UIViewController).view.backgroundColor = .red
(lldb) expr let $snapshot = self.view.debugQuickLookObject()

LLDB-তে Python স্ক্রিপ্টিং

Python API LLDB-তে ডিবাগিং অটোমেশনের জন্য স্ক্রিপ্ট লেখার অনুমতি দেয়। Python-এর মাধ্যমে, কাস্টম কমান্ড তৈরি করা, ব্রেকপয়েন্ট ইভেন্ট হ্যান্ডল করা, রিপোর্ট জেনারেট করা এবং এমনকি ডিবাগারের আচরণ ওভাররাইড করা যায়। বিল্ট-ইন Python 3 ইন্টারপ্রেটার lldb মডিউলের মাধ্যমে সম্পূর্ণ ডিবাগিং API-তে অ্যাক্সেস সহ সরাসরি LLDB-এর ভিতরে চলে।

কাস্টম কমান্ড তৈরি

Python স্ক্রিপ্টে @classmethod ডেকোরেটরের মাধ্যমে একটি নতুন LLDB কমান্ড নিবন্ধন করা যেতে পারে। স্ক্রিপ্ট ইম্পোর্ট করার পরে, কমান্ডটি বিল্ট-ইন হিসাবে উপলব্ধ হয়। উদাহরণস্বরূপ, printvars কমান্ড বর্তমান ফ্রেমের সমস্ত ভেরিয়েবল তাদের প্রকার এবং মান সহ, একটি নির্দিষ্ট প্রজেক্টের জন্য ফরম্যাট করে আউটপুট দিতে পারে। Stack Overflow-এ iOS ডেভেলপারদের একটি জরিপ অনুসারে, অটোমেশন সাধারণ ডিবাগ অপারেশনের সময় 60–80% কমিয়ে দেয়।

python
import lldb

class PrintVarsCommand:
    @classmethod
    def register_class(cls, debugger, _):
        handler = PrintVarsCommand()
        debugger.HandleCommand('command script add -c \
            print_vars.PrintVarsCommand printvars')

    def __call__(self, debugger, command, exe_ctx, result):
        frame = exe_ctx.frame
        for var in frame.variables:
            result.AppendMessage(f"{var.name}: {var.type} = {var.value}")

ব্রেকপয়েন্ট ইভেন্ট হ্যান্ডলিং

Python API-এর মাধ্যমে, একটি স্ক্রিপ্ট ব্রেকপয়েন্ট ফায়ারিং-এর সাথে বাঁধা যেতে পারে। একটি ব্রেকপয়েন্ট সেট করুন, তারপর breakpoint command add চালান এবং একটি Python ফাংশন নির্দিষ্ট করুন। এটি ম্যানুয়াল হস্তক্ষেপ ছাড়াই স্বয়ংক্রিয়ভাবে অবস্থা লগ করা, ডেটা অ্যানালিটিক্সে পাঠানো বা ইনভেরিয়েন্ট চেক করার অনুমতি দেয়। LLVM-এর মতে, এই পদ্ধতিটি Apple-এর অবকাঠামোতে ডেভেলপমেন্টের সময় পারফরম্যান্স মেট্রিক্স সংগ্রহ করতে ব্যবহৃত হয়।

lldb
(lldb) breakpoint set -f Model.swift -l 100
(lldb) breakpoint command add 1 -s python -o "frame = exe_ctx.frame;
  print([var.name for var in frame.variables])"

REPL মোড এবং প্লেগ্রাউন্ড

REPL (Read-Eval-Print Loop) হল LLDB-এর একটি ইন্টারঅ্যাকটিভ মোড, যা lldb --repl কমান্ড বা Xcode ডিবাগ কনসোলের মাধ্যমে আহ্বান করা হয়। REPL-এ, আপনি প্লেগ্রাউন্ডের মতো Swift বা C কোড নির্বাহ করতে পারেন, তাত্ক্ষণিক প্রতিক্রিয়া সহ। LLDB প্রতিটি লাইন কম্পাইল করে, তা নির্বাহ করে এবং ফলাফল দেখায় — APIs নিয়ে পরীক্ষা, অ্যালগরিদম প্রোটোটাইপিং এবং প্রজেক্ট তৈরি না করেই ভাষার নতুন বৈশিষ্ট্য শেখার জন্য সুবিধাজনক।

lldb
(lldb) --repl
1> let numbers = [1, 2, 3, 4, 5]
2> numbers.filter { $0 % 2 == 0 }
$R0: [Int] = 2 values {
  [0] = 2
  [1] = 4
}
3> let result = numbers.reduce(0, +)
$R1: Int = 15

REPL মোড import-এর মাধ্যমে মডিউল এবং ফ্রেমওয়ার্ক লোড করাও সমর্থন করে। উদাহরণস্বরূপ, REPL-এ import UIKit সম্পূর্ণ UIKit লাইব্রেরি লোড করে, এবং UI উপাদান তৈরি, কনস্ট্রেন্ট চেক এবং অ্যানিমেশন পরীক্ষা করা যেতে পারে। এটি iOS ডেভেলপারদের জন্য একটি অনন্য ক্ষমতা, যা GDB-তে অনুপলব্ধ — একই পরিবেশে ডিবাগিং এবং প্রোটোটাইপিং।

Swift শেখার জন্য REPL ব্যবহার

Swift কম্পাইলার-এর সাথে একীকরণের কারণে, LLDB REPL Apple কোর্সে Swift শেখানোর জন্য ব্যবহৃত হয়। শিক্ষার্থীরা প্রজেক্ট সেটআপে বিভ্রান্ত না হয়ে, লাইন ধরে কোড নির্বাহ করতে পারে, প্রকার এবং ফলাফল দেখতে পারে। এই পদ্ধতি Active Learning পদ্ধতি অনুসরণ করে, যেখানে ইন্টারঅ্যাকটিভ ফিডব্যাক কম্পিউটার সায়েন্স এডুকেশনের গবেষণা অনুসারে উপাদান বোঝা 40% পর্যন্ত ত্বরান্বিত করে।

প্রায়শই জিজ্ঞাসিত প্রশ্ন

LLDB কীভাবে GDB থেকে আলাদা?

LLDB একটি মডুলার LLVM আর্কিটেকচারের উপর নির্মিত, যা এটি এক্সপ্রেশন মূল্যায়নের গতি এবং আধুনিক ভাষার (Swift) সমর্থনে সুবিধা দেয়। GDB হল একটি একচেটিয়া ডিবাগার যা Swift সমর্থন করে না এবং এর সীমিত স্ক্রিপ্টিং ক্ষমতা রয়েছে।

Xcode ছাড়া macOS-এ LLDB REPL কীভাবে চালাবেন?

xcode-select --install-এর মাধ্যমে Command Line Tools ইনস্টল করুন, তারপর টার্মিনালে lldb --repl চালান। LLDB /Library/Developer/CommandLineTools/usr/bin/-এ উপলব্ধ।

LLDB কি আগে থেকে চলমান প্রক্রিয়ার সাথে সংযুক্ত করা যাবে?

হ্যাঁ, lldb --attach-pid PID বা process attach --name AppName-এর মাধ্যমে। LLDB প্রক্রিয়াটি থামিয়ে দেবে, যার পরে অ্যাপ্লিকেশন পুনরায় চালু না করেই সমস্ত স্ট্যান্ডার্ড ডিবাগ কমান্ড উপলব্ধ।

LLDB কেন সোর্স কোডের পরিবর্তে অ্যাসেম্বলি দেখায়?

dSYM ডিবাগ তথ্য ফাইল অনুপস্থিত। Build Settings চেক করুন: Generate Debug Symbols অবশ্যই YES হতে হবে, এবং Debug Information Format অবশ্যই DWARF with dSYM File হতে হবে।

LLDB কমান্ড ইতিহাস কীভাবে সংরক্ষণ করবেন?

LLDB স্বয়ংক্রিয়ভাবে ইতিহাস ~/.lldb/lldb-history-এ সংরক্ষণ করে। এক্সপোর্টের জন্য, session save filename.txt ব্যবহার করুন — কমান্ডটি বর্তমান সেশনের সমস্ত নির্বাহিত কমান্ড একটি টেক্সট ফাইলে সংরক্ষণ করে।

সারসংক্ষেপ

  • LLDB হল LLVM প্রজেক্টের একটি পরবর্তী প্রজন্মের ডিবাগার, যা Xcode এবং সম্পূর্ণ Apple ইকোসিস্টেমের জন্য মানক।
  • মডুলার আর্কিটেকচার Core, Expression Parser, Symbol File এবং Interpreter লাইব্রেরি সহ।
  • LLDB কমান্ড নির্বাহ নিয়ন্ত্রণ, ব্রেকপয়েন্ট, ডেটা পরিদর্শন এবং এক্সপ্রেশন মূল্যায়নে বিভক্ত।
  • চলাকালীন এক্সপ্রেশন মূল্যায়ন একটি মূল ক্ষমতা যা পুনরায় চালু না করেই কোড পরীক্ষার অনুমতি দেয়।
  • Python API স্ক্রিপ্টের মাধ্যমে ডিবাগারের উপর সম্পূর্ণ নিয়ন্ত্রণ প্রদান করে: কাস্টম কমান্ড, ব্রেকপয়েন্ট হ্যান্ডলিং, রিপোর্ট।
  • REPL মোড Swift এবং C-এর জন্য একটি ইন্টারঅ্যাকটিভ প্লেগ্রাউন্ড হিসাবে কাজ করে, শেখা এবং প্রোটোটাইপিংয়ের জন্য দরকারী।
  • dSYM ফাইল ক্র্যাশ লগ প্রতীকী করতে এবং সোর্স কোড সঠিকভাবে প্রদর্শনের জন্য প্রয়োজনীয়।

আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব

IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।

প্রকল্প নিয়ে আলোচনা করুন

আরও পড়ুন